📄 textsw_seln_svc.c
字号:
#ifndef lint#ifdef sccsstatic char sccsid[] = "@(#)textsw_seln_svc.c 1.1 92/07/30";#endif#endif/* * Copyright (c) 1986, 1987 by Sun Microsystems, Inc. *//* * Textsw interface to selection service. */#include <errno.h>#include <suntool/primal.h>#include <suntool/textsw_impl.h>#include <suntool/alert.h>#include <suntool/frame.h>#include "sunwindow/sv_malloc.h"extern int errno;extern Es_status es_copy();static Seln_result textsw_seln_yield();char *shelf_name = "/tmp/textsw_shelf";#define SAME_HOLDER(folio, holder) \ seln_holder_same_client(holder, folio->first_view)typedef struct continuation { int in_use, type; Es_index current, first, last_plus_one; unsigned span_level;} Continuation_object;typedef Continuation_object * Continuation;static Continuation_object fast_continuation; /* Default init to zeros */pkg_private voidtextsw_clear_secondary_selection(textsw, type) register Textsw_folio textsw; unsigned type;{ if (type & EV_SEL_SECONDARY) { if (type & TFS_IS_OTHER) { Seln_holder holder; holder = seln_inquire(SELN_SECONDARY); if (holder.state != SELN_NONE) (void) seln_ask(&holder, SELN_REQ_YIELD, 0, 0); } else { textsw_set_selection(VIEW_REP_TO_ABS(textsw->first_view), ES_INFINITY, ES_INFINITY, type); } }}static unsignedholder_flag_from_seln_rank(rank) register Seln_rank rank;{ switch (rank) { case SELN_CARET: return(TXTSW_HOLDER_OF_CARET); case SELN_PRIMARY: return(TXTSW_HOLDER_OF_PSEL); case SELN_SECONDARY: return(TXTSW_HOLDER_OF_SSEL); case SELN_SHELF: return(TXTSW_HOLDER_OF_SHELF); case SELN_UNSPECIFIED: return(0); default: LINT_IGNORE(ASSUME(0)); return(0); }}static unsignedev_sel_type_from_seln_rank(rank) register Seln_rank rank;{ switch (rank) { case SELN_CARET: return(EV_SEL_CARET); case SELN_PRIMARY: return(EV_SEL_PRIMARY); case SELN_SECONDARY: return(EV_SEL_SECONDARY); case SELN_SHELF: return(EV_SEL_SHELF); default: LINT_IGNORE(ASSUME(0)); return(0); }}static unsignedholder_flag_from_textsw_info(type) register unsigned type;{ if (type & EV_SEL_CARET) return(TXTSW_HOLDER_OF_CARET); if (type & EV_SEL_PRIMARY) return(TXTSW_HOLDER_OF_PSEL); if (type & EV_SEL_SECONDARY) return(TXTSW_HOLDER_OF_SSEL); if (type & EV_SEL_SHELF) return(TXTSW_HOLDER_OF_SHELF); return(0);}pkg_private Seln_rankseln_rank_from_textsw_info(type) register unsigned type;{ if (type & EV_SEL_CARET) return(SELN_CARET); if (type & EV_SEL_PRIMARY) return(SELN_PRIMARY); if (type & EV_SEL_SECONDARY) return(SELN_SECONDARY); if (type & EV_SEL_SHELF) return(SELN_SHELF); return(SELN_UNKNOWN);}/* The following acquires the selection of the specified rank unless the * textsw already holds it. */pkg_private Seln_ranktextsw_acquire_seln(textsw, rank) register Textsw_folio textsw; register Seln_rank rank;{ unsigned holder_flag; if (textsw_should_ask_seln_svc(textsw, TRUE)) { if ((textsw->holder_state & holder_flag_from_seln_rank(rank)) == 0) { rank = seln_acquire(textsw->selection_client, rank); } } else if (rank == SELN_UNSPECIFIED) { textsw->holder_state |= TXTSW_HOLDER_OF_ALL; return(SELN_UNKNOWN); /* Don't fall through as that will bump time-of-death */ } holder_flag = holder_flag_from_seln_rank(rank); if (holder_flag) { textsw->holder_state |= holder_flag; } else { Event alert_event; int result; /* Assume svc temporarily dead, but make sure timer is set before * calling textsw_post_error because it will result in a recursive * call on this routine via textsw_may_win_exit if the timer is * clear. */ gettimeofday(&textsw->selection_died, (struct timezone *)0); result = alert_prompt( (Frame)window_get(WINDOW_FROM_VIEW(textsw), WIN_OWNER), &alert_event, ALERT_MESSAGE_STRINGS, "Cannot contact Selection Service - pressing", " on but selections across windows may not work.", 0, ALERT_BUTTON_YES, "Continue", 0); if (result == ALERT_FAILED) { fprintf(stderr, "ALERT_FAILED!\nCannot contact Selection Service - pressing on but selections across windows may not work.\n"); } textsw->holder_state |= TXTSW_HOLDER_OF_ALL; } return(rank);}/* ========================================================== * * Routines to support the use of selections. * * ========================================================== */#define TXTSW_NEED_SELN_CLIENT (Seln_client)1#define MIN_SELN_TIMEOUT 0#define DEFAULT_SELN_TIMEOUT 10 /* 10 seconds */#define MAX_SELN_TIMEOUT 300 /* 5 minutes */static inttextsw_should_ask_seln_svc(textsw, retry_okay) register Textsw_folio textsw; int retry_okay;{ pkg_private void textsw_seln_svc_function(); pkg_private Seln_result textsw_seln_svc_reply(); struct timeval now; int result; Event alert_event; int selection_timeout; if (textsw->state & TXTSW_DELAY_SEL_INQUIRE) { textsw->state &= ~TXTSW_DELAY_SEL_INQUIRE; return(textsw_sync_with_seln_svc(textsw)); } if (textsw->selection_client == 0) return(FALSE); if (timerisset(&textsw->selection_died)) { if (!retry_okay) return(FALSE); /* Retry if contact lost at least 60 seconds ago */ gettimeofday(&now, (struct timezone *)0); if (now.tv_sec < textsw->selection_died.tv_sec + 60) return(FALSE); /* textsw_post_error will eventually call textsw_may_win_exit * which will call textsw_should_ask_seln_svc (with retry_okay set * to FALSE), but we must make sure that the timer is still set * on that recursive call, so don't clear it until AFTER * textsw_post_error returns! */ result = alert_prompt( (Frame)window_get(WINDOW_FROM_VIEW(textsw), WIN_OWNER), &alert_event, ALERT_MESSAGE_STRINGS, "textsw: attempting to re-contact Selection Service", " - selections may be temporarily incorrect.", 0, ALERT_BUTTON_YES, "Continue", 0); if (result == ALERT_FAILED) { fprintf(stderr,"ALERT_FAILED!\ntextsw: attempting to re-contact Selection Service - selections may be temporarily incorrect.\n"); } timerclear(&textsw->selection_died); } if (textsw->selection_client == TXTSW_NEED_SELN_CLIENT) { 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 */ /* Try to establish the initial connection with Seln. Svc. */ textsw->selection_client = seln_create( textsw_seln_svc_function, textsw_seln_svc_reply, (caddr_t)LINT_CAST(textsw->first_view)); if (textsw->selection_client == 0) { int result; Event alert_event; /* Set up to retry later and then tell user we lost. */ textsw->selection_client = TXTSW_NEED_SELN_CLIENT; gettimeofday(&textsw->selection_died, (struct timezone *)0); result = alert_prompt( (Frame)window_get(WINDOW_FROM_VIEW(textsw), WIN_OWNER), &alert_event, ALERT_MESSAGE_STRINGS, "textsw: cannot initiate contact with Selection", " Service; pressing on and will retry later", 0, ALERT_BUTTON_YES, "Continue", 0); if (result == ALERT_FAILED) { fprintf(stderr,"ALERT_FAILED!\ntextsw: cannot initiate contact with Selection Service; pressing on and will retry later\n"); } return(FALSE); } } return(TRUE);}pkg_private unsignedtextsw_determine_selection_type(textsw, acquire) register Textsw_folio textsw; int acquire;{ register unsigned result; register int ask_svc = textsw_should_ask_seln_svc(textsw, TRUE); register Seln_rank rank; Seln_holder holder; if (textsw->holder_state & TXTSW_HOLDER_OF_SSEL) { if ((textsw->holder_state & TXTSW_HOLDER_OF_ALL) == TXTSW_HOLDER_OF_ALL) { ask_svc = 0; } else { Firm_event focus; int shift; if (!win_get_focus_event(WIN_FD_FOR_VIEW(textsw->first_view), &focus, &shift)) { ask_svc = (focus.id != LOC_WINENTER); } } if (!ask_svc) result = (textsw->track_state & TXTSW_TRACK_SECONDARY) ? EV_SEL_SECONDARY : EV_SEL_PRIMARY; }#ifdef DEBUG_SVCfprintf(stderr, "Holders: %d%s", textsw->holder_state & TXTSW_HOLDER_OF_ALL, (ask_svc) ? "\t" : "\n");#endif if (ask_svc) { if (acquire == 0) { holder = seln_inquire(SELN_UNSPECIFIED); result = (holder.rank == SELN_SECONDARY) ? EV_SEL_SECONDARY : EV_SEL_PRIMARY; } else { rank = textsw_acquire_seln(textsw, SELN_UNSPECIFIED);#ifdef DEBUG_SVCfprintf(stderr, "textsw_acquire_seln returned rank = %d\n", (int)rank);#endif switch (rank) { case SELN_PRIMARY: result = EV_SEL_PRIMARY; textsw->track_state &= ~TXTSW_TRACK_SECONDARY; break; case SELN_SECONDARY: result = EV_SEL_SECONDARY; textsw->track_state |= TXTSW_TRACK_SECONDARY; if (textsw->func_state) { } else if (seln_get_function_state(SELN_FN_DELETE)) { /* Act as if it was local DELETE down */ textsw->func_state |= TXTSW_FUNC_DELETE| TXTSW_FUNC_SVC_SAW(TXTSW_FUNC_DELETE); if (!TXTSW_IS_READ_ONLY(textsw)) textsw->state |= TXTSW_PENDING_DELETE; } else if (seln_get_function_state(SELN_FN_PUT)) { /* Act as if it was local PUT down */ textsw_begin_put(textsw->first_view, 0); textsw->func_state |= TXTSW_FUNC_SVC_SAW(TXTSW_FUNC_PUT); } break; default: /* Assume svc temporarily dead */ result = EV_SEL_PRIMARY; break; } } } else if (textsw->selection_client == 0) { textsw->holder_state |= TXTSW_HOLDER_OF_ALL; } if (textsw->state & TXTSW_PENDING_DELETE) { result |= (textsw->track_state & TXTSW_TRACK_SECONDARY) ? EV_SEL_PD_SECONDARY : EV_SEL_PD_PRIMARY; } return(result);}/* For function keys that deal with selections, the following cases must be * considered as plausible: * No primary selection * (See below for subcases) * Primary selection in window A (our window) * FN key DOWN in window A * No secondary selection * FN key UP in window A * FN key UP in window B (some other window) * Secondary selection in window A * FN key UP in window A * FN key UP in window B * Secondary selection in window B * FN key UP in window A * FN key UP in window B * FN key DOWN in window B * No secondary selection * FN key UP in window A * FN key UP in window B * Secondary selection in window A * FN key UP in window A * FN key UP in window B * Secondary selection in window B * FN key UP in window A * FN key UP in window B * Primary selection in window B * (See above for subcases) * * On the FN key UP, the cases can be viewed as: * DOWN in same window => inform service iff informed it about DOWN * DOWN in other window => inform other window via service * * Window that is to process FN key (assumed to be holder of Primary * selection) has three UP cases to deal with: * UP in this window, service not informed => * process directly/locally, any Secondary selection is local * UP in this window, service informed (by this window) || * UP in other window =>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -