📄 ttyselect.c
字号:
#ifndef lint#ifdef sccsstatic char sccsid[] = "@(#)ttyselect.c 1.1 92/07/30 Copyr 1985 Sun Micro";#endif#endif/* * Copyright (c) 1985 by Sun Microsystems, Inc. */#include <signal.h>#include <stdio.h>#include <ctype.h>#include <sys/types.h>#include <sys/file.h>#include <sys/time.h>#include <sundev/kbd.h>#include <pixrect/pixrect.h>#include <pixrect/pixfont.h>#include <sunwindow/rect.h>#include <sunwindow/rectlist.h>#include <sunwindow/cms.h>#include <sunwindow/pixwin.h>#include <sunwindow/win_input.h>#include <suntool/tool.h>#include <suntool/selection.h>#include <suntool/selection_svc.h>#include <suntool/selection_attributes.h>#include <suntool/ttysw.h>#include <suntool/ttysw_impl.h>#include <suntool/ttyansi.h>#include <suntool/charimage.h>#include <suntool/charscreen.h>#define MIN_SELN_TIMEOUT 0#define DEFAULT_SELN_TIMEOUT 10 /* 10 seconds */#define MAX_SELN_TIMEOUT 300 /* 5 minutes *//* global which can be used to make a shell tool which * doesn't talk to the service */int ttysel_use_seln_service = 1;/* global & private procedures */void ttyhiliteselection();static void tvsub(), ttycountchars(), ttyenumerateselection(), ttyhiliteline(), ttysel_empty(), ttysel_resolve(), ttysortextents(), ttysel_read(), ttysel_write(), ttyputline(), ttysel_function(), ttysel_end_request();static int ttysel_insel(), ttysel_eq();static Seln_result ttysel_copy_in(), ttysel_copy_out(), ttysel_reply();static struct ttyselection * ttysel_from_rank();struct ttysel_context { unsigned continued; struct ttysubwindow *ttysw; unsigned bytes_left;};#define SEL_NULLPOS -1#define TSE_NULL_EXTENT {SEL_NULLPOS, SEL_NULLPOS}static struct textselpos tse_null_extent = TSE_NULL_EXTENT;static struct ttyselection ttysw_nullttysel = { 0, 0, SEL_CHAR, 0, TSE_NULL_EXTENT, TSE_NULL_EXTENT, {0, 0}};static struct ttysubwindow *ttysel_ttysw; /* stash for ttysel_read */static struct ttyselection *ttysel_ttysel; /* stash for ttysel_write */static struct timeval maxinterval = {0, 400000}; /* XXX - for now */static char *ttysel_filename = "/tmp/ttyselection";intttysw_is_seln_nonzero(ttysw, rank) register struct ttysubwindow *ttysw; Seln_rank rank;{ Seln_holder holder; Seln_request *req_buf; char **argv; int bytesize = 0; if (!ttysw_getopt((caddr_t)ttysw, TTYOPT_SELSVC)) { return 0; } holder = seln_inquire(rank); if (holder.state != SELN_NONE) { req_buf = seln_ask(&holder, SELN_REQ_BYTESIZE, 0, 0); argv = (char **)LINT_CAST(req_buf->data); if (*argv++ == (char *)SELN_REQ_BYTESIZE) { bytesize = (int)*argv; } } return bytesize;}/* * init_client: */voidttysel_init_client(ttysw) register struct ttysubwindow *ttysw;{ int selection_timeout; if (!ttysw_getopt((caddr_t)ttysw, TTYOPT_SELSVC)) { return; } ttysw->ttysw_caret = ttysw_nullttysel; ttysw->ttysw_primary = ttysw_nullttysel; ttysw->ttysw_secondary = ttysw_nullttysel; ttysw->ttysw_shelf = ttysw_nullttysel; selection_timeout = defaults_get_integer_check("/SunView/Selection_Timeout", DEFAULT_SELN_TIMEOUT, MIN_SELN_TIMEOUT, MAX_SELN_TIMEOUT, 0); seln_use_timeout(selection_timeout); /* set selection timeout */ ttysw->ttysw_seln_client = seln_create(ttysel_function, ttysel_reply, (char *) ttysw); if (ttysw->ttysw_seln_client == (char *) NULL) { (void)ttysw_setopt((caddr_t)ttysw, TTYOPT_SELSVC, FALSE); }}voidttysel_destroy(ttysw) register struct ttysubwindow *ttysw;{ if (!ttysw_getopt((caddr_t)ttysw, TTYOPT_SELSVC)) { return; } if (ttysw->ttysw_seln_client != (char *) NULL) { seln_destroy(ttysw->ttysw_seln_client); ttysw->ttysw_seln_client = (char *) NULL; }}/* * Make sure we have desired selection. */voidttysel_acquire(ttysw, sel_desired) register struct ttysubwindow *ttysw; register Seln_rank sel_desired;{ register Seln_rank sel_received; register struct ttyselection *ttysel; if (!ttysw_getopt((caddr_t)ttysw, TTYOPT_SELSVC)) { return; } ttysel = ttysel_from_rank(ttysw, sel_desired); if (!ttysel->sel_made) { if (sel_desired == SELN_CARET) { Seln_holder holder; holder = seln_inquire(SELN_UNSPECIFIED); if (holder.rank != SELN_PRIMARY) return; } sel_received = seln_acquire(ttysw->ttysw_seln_client, sel_desired); if (sel_received == sel_desired) { ttysel->sel_made = TRUE; ttysel_empty(ttysel); } else { (void)seln_done(ttysw->ttysw_seln_client, sel_received); } }}/* * Return rank of global selection state. */Seln_rankttysel_mode(ttysw) struct ttysubwindow *ttysw;{ Seln_holder sel_holder; if (!ttysw_getopt((caddr_t)ttysw, TTYOPT_SELSVC)) { return SELN_PRIMARY; } else { sel_holder = seln_inquire(SELN_UNSPECIFIED); return sel_holder.rank; }}/* * Make a new selection. If multi is set, check for multi-click. */voidttysel_make(ttysw, event, multi) register struct ttysubwindow *ttysw; register struct inputevent *event; int multi;{ register Seln_rank sel_received; register struct ttyselection *ttysel; struct textselpos tspb, tspe; struct timeval td; if (!ttysw_getopt((caddr_t)ttysw, TTYOPT_SELSVC)) { sel_received = SELN_PRIMARY; } else { sel_received = seln_acquire(ttysw->ttysw_seln_client, SELN_UNSPECIFIED); } if (sel_received == SELN_PRIMARY) { ttysel = &ttysw->ttysw_primary; if (ttysw_getopt((caddr_t)ttysw, TTYOPT_SELSVC)) { ttysel_acquire(ttysw, SELN_CARET); } if (ttysw->ttysw_secondary.sel_made) { (void)ttysel_cancel(ttysw, SELN_SECONDARY); /* insurance */ } } else if (sel_received == SELN_SECONDARY) { ttysel = &ttysw->ttysw_secondary; } else { return; } ttysel_resolve(&tspb, &tspe, SEL_CHAR, event); if (multi && ttysel->sel_made) { tvsub(&td, &event->ie_time, &ttysel->sel_time); if (ttysel_insel(ttysel, &tspe) && timercmp(&td, &maxinterval, <)) { (void)ttysel_adjust(ttysw, event, 1); return; } } if (ttysel->sel_made) ttysel_deselect(ttysel, sel_received); ttysel->sel_made = TRUE; ttysel->sel_begin = tspb; ttysel->sel_end = tspe; ttysel->sel_time = event->ie_time; ttysel->sel_level = SEL_CHAR; ttysel->sel_anchor = 0; ttysel->sel_null = FALSE; ttyhiliteselection(ttysel, sel_received);}/* * Move the current selection. */voidttysel_move(ttysw, event) register struct ttysubwindow *ttysw; register struct inputevent *event;{ register Seln_rank rank; register struct ttyselection *ttysel; struct textselpos tspb, tspe; if (ttysw->ttysw_secondary.sel_made) { rank = SELN_SECONDARY; ttysel = &ttysw->ttysw_secondary; } else if (ttysw->ttysw_primary.sel_made) { rank = SELN_PRIMARY; ttysel = &ttysw->ttysw_primary; } else { return; } ttysel_resolve(&tspb, &tspe, ttysel->sel_level, event); ttyhiliteselection(ttysel, rank); ttysel->sel_begin = tspb; ttysel->sel_end = tspe; ttysel->sel_time = event->ie_time; ttysel->sel_anchor = 0; ttysel->sel_null = FALSE; ttyhiliteselection(ttysel, rank);}/* * Adjust the current selection according to the event. * If multi is set, check for multi-click. */ttysel_adjust(ttysw, event, multi) register struct ttysubwindow *ttysw; struct inputevent *event; int multi;{ register struct textselpos *tb; register struct textselpos *te; Seln_rank rank; int count; int extend = 0; struct textselpos tspc, tspb, tspe, tt; struct ttyselection *ttysel; struct timeval td; if (ttysw->ttysw_secondary.sel_made) { rank = SELN_SECONDARY; ttysel = &ttysw->ttysw_secondary; } else if (ttysw->ttysw_primary.sel_made) { rank = SELN_PRIMARY; ttysel = &ttysw->ttysw_primary; } else { return; } tb = &ttysel->sel_begin; te = &ttysel->sel_end; if (!ttysel->sel_made || ttysel->sel_null) return; ttysel_resolve(&tspb, &tspc, SEL_CHAR, event); if (multi) { tvsub(&td, &event->ie_time, &ttysel->sel_time); if (ttysel_insel(ttysel, &tspc) && timercmp(&td, &maxinterval, <)) { extend = 1; if (++ttysel->sel_level > SEL_MAX) { ttysel->sel_level = SEL_CHAR; extend = 0; } } ttysel->sel_time = event->ie_time; ttysel->sel_anchor = 0; } ttysel_resolve(&tspb, &tspe, ttysel->sel_level, event); /* * If inside current selection, pull in closest end. */ if (!extend && ttysel_insel(ttysel, &tspc)) { int left_end, right_end; if (ttysel->sel_anchor == 0) { /* count chars to left */ count = 0; tt = *te; *te = tspc; ttyenumerateselection(ttysel, ttycountchars, (char *)(&count)); *te = tt; left_end = count; /* count chars to right */ count = 0; tt = *tb; *tb = tspc; ttyenumerateselection(ttysel, ttycountchars, (char *)(&count)); *tb = tt; right_end = count; if (right_end <= left_end) ttysel->sel_anchor = -1; else ttysel->sel_anchor = 1; } if (ttysel->sel_anchor == -1) { if (!ttysel_eq(te, &tspe)) { /* pull in right end */ tt = *tb; *tb = tspe; tb->tsp_col++; ttyhiliteselection(ttysel, rank); *tb = tt; *te = tspe; } } else { if (!ttysel_eq(tb, &tspb)) { /* pull in left end */ tt = *te; *te = tspb; te->tsp_col--; ttyhiliteselection(ttysel, rank); *te = tt; *tb = tspb; } } } else { /* * Determine which end to extend. Both ends may extend if selection * level has increased. */ int newanchor = 0; if (tspe.tsp_row > te->tsp_row || tspe.tsp_row == te->tsp_row && tspe.tsp_col > te->tsp_col) { /* extend right end */ if (ttysel->sel_anchor == 1) { ttysel->sel_anchor = -1; ttyhiliteselection(ttysel, rank); *tb = *te; ttyhiliteselection(ttysel, rank); } else if (ttysel->sel_anchor == 0) newanchor = -1; tt = *tb; *tb = *te; tb->tsp_col++; /* check for overflow? */ *te = tspe; ttyhiliteselection(ttysel, rank); *tb = tt; } if (tspb.tsp_row < tb->tsp_row || tspb.tsp_row == tb->tsp_row && tspb.tsp_col < tb->tsp_col) { /* extend left end */ if (ttysel->sel_anchor == -1) { ttysel->sel_anchor = 1; ttyhiliteselection(ttysel, rank); *te = *tb; ttyhiliteselection(ttysel, rank); } else if (ttysel->sel_anchor == 0) if (newanchor == 0) newanchor = 1; else newanchor = 0; tt = *te; *te = *tb; te->tsp_col--; /* check for underflow? */ *tb = tspb; ttyhiliteselection(ttysel, rank); *te = tt; } if (ttysel->sel_anchor == 0) ttysel->sel_anchor = newanchor; }}/* * Clear out the current selection. */ttysel_cancel(ttysw, rank) register struct ttysubwindow *ttysw; Seln_rank rank;{ struct ttyselection *ttysel; switch (rank) { case SELN_CARET: ttysel = &ttysw->ttysw_caret; break; case SELN_PRIMARY: ttysel = &ttysw->ttysw_primary; break; case SELN_SECONDARY: ttysel = &ttysw->ttysw_secondary; break; case SELN_SHELF: ttysel = &ttysw->ttysw_shelf; break; default: return; } if (!ttysel->sel_made) return; ttysel_deselect(ttysel, rank); ttysel->sel_made = FALSE; if (!ttysw_getopt((caddr_t)ttysw, TTYOPT_SELSVC)) (void)seln_done(ttysw->ttysw_seln_client, rank);}/* XXX - compatibility kludge */voidttynullselection(ttysw) struct ttysubwindow *ttysw;{ (void)ttysel_cancel(ttysw, SELN_PRIMARY);}/* * Remove a selection from the screen */voidttysel_deselect(ttysel, rank) register struct ttyselection *ttysel; Seln_rank rank;{ if (!ttysel->sel_made) return; ttyhiliteselection(ttysel, rank); if (!ttysel->sel_null) ttysel_empty(ttysel);}/* * check all selections, and hilite any that exist */voidttysel_hilite(ttysw) register struct ttysubwindow *ttysw;{/* struct ttyselection *ttysel; Delete this? */ if (ttysw->ttysw_primary.sel_made) ttyhiliteselection(&ttysw->ttysw_primary, SELN_PRIMARY); if (ttysw->ttysw_secondary.sel_made) ttyhiliteselection(&ttysw->ttysw_secondary, SELN_SECONDARY);}/* * Hilite a selection. * Enumerate all the lines of the selection; hilite each one as appropriate. */voidttyhiliteselection(ttysel, rank) register struct ttyselection *ttysel; Seln_rank rank;{ struct pr_size offsets; if (!ttysel->sel_made || ttysel->sel_null) { return; } switch (rank) { case SELN_SECONDARY: offsets.x = (chrheight + chrbase) / 2; offsets.y = 1; break; case SELN_PRIMARY: offsets.x = 0; offsets.y = chrheight; } ttyenumerateselection(ttysel, ttyhiliteline, (char *)(&offsets));}/* * Set local selection as global one. */voidttysetselection(ttysw) register struct ttysubwindow *ttysw;{ int count; struct selection selection; struct ttyselection *ttysel; if (ttysw->ttysw_secondary.sel_made || !ttysw->ttysw_primary.sel_made) return; ttysel = &ttysw->ttysw_primary; ttysel_ttysel = ttysel; /* stash for ttysel_write */ selection = selnull; selection.sel_type = SELTYPE_CHAR; count = 0; ttyenumerateselection(ttysel, ttycountchars, (char *)(&count)); selection.sel_items = count; selection.sel_itembytes = 1; selection.sel_pubflags = SEL_PRIMARY; selection.sel_privdata = 0; (void)selection_set(&selection, (int (*)())(LINT_CAST(ttysel_write)), (int (*)())0, ttysw->ttysw_wfd);}/* * Read global selection into input stream. */voidttygetselection(ttysw) struct ttysubwindow *ttysw;{ ttysel_ttysw = ttysw; /* stash for ttysel_read */ (void)selection_get((int (*)())(LINT_CAST(ttysel_read)), ttysw->ttysw_wfd);}/* internal (static) routines *//* * convert from a selection rank to a ttysel struct */static struct ttyselection *ttysel_from_rank(ttysw, rank) struct ttysubwindow *ttysw; Seln_rank rank;{ switch (rank) { case SELN_CARET: return &ttysw->ttysw_caret; case SELN_PRIMARY: return &ttysw->ttysw_primary; case SELN_SECONDARY: return &ttysw->ttysw_secondary; case SELN_SHELF: return &ttysw->ttysw_shelf; default: break; } return (struct ttyselection *) NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -