📄 textsw_seln_svc.c
字号:
* Secondary selection can be: * local => process directly * remote => process indirectly * non-existent => * Primary selection can be: * local => process directly * remote => process indirectly * non-existent => no-op */pkg_private voidtextsw_give_shelf_to_svc(folio) register Textsw_folio folio;{ extern Es_handle es_file_create(); register Es_handle output; Es_status create_status, copy_status; if (folio->trash == ES_NULL) return; if (!textsw_should_ask_seln_svc(folio, TRUE)) return; /* Write the contents to a file */ output = es_file_create(shelf_name, ES_OPT_APPEND, &create_status); /* If create failed due to permission problem, retry */ if ((output == 0) && (create_status == ES_CHECK_ERRNO) && (errno == EACCES)) { unlink(shelf_name); output = es_file_create(shelf_name, ES_OPT_APPEND, &create_status); } if (output) { copy_status = es_copy(folio->trash, output, FALSE); if (copy_status == ES_SUCCESS) { seln_hold_file(SELN_SHELF, shelf_name); folio->holder_state &= ~TXTSW_HOLDER_OF_SHELF; } es_destroy(output); } /* Now destroy the trashbin */ es_destroy(folio->trash); folio->trash = ES_NULL;}pkg_private inttextsw_sync_with_seln_svc(folio) register Textsw_folio folio;{ Seln_holders_all holders; int result; if (result = textsw_should_ask_seln_svc(folio, TRUE)) { holders = seln_inquire_all(); if (SAME_HOLDER(folio, (caddr_t)LINT_CAST(&holders.caret))) { folio->holder_state |= TXTSW_HOLDER_OF_CARET; } else { folio->holder_state &= ~TXTSW_HOLDER_OF_CARET; } if (SAME_HOLDER(folio, (caddr_t)LINT_CAST(&holders.primary))) { folio->holder_state |= TXTSW_HOLDER_OF_PSEL; } else { folio->holder_state &= ~TXTSW_HOLDER_OF_PSEL; } if (SAME_HOLDER(folio, (caddr_t)LINT_CAST(&holders.secondary))) { folio->holder_state |= TXTSW_HOLDER_OF_SSEL; } else { folio->holder_state &= ~TXTSW_HOLDER_OF_SSEL; } if (SAME_HOLDER(folio, (caddr_t)LINT_CAST(&holders.shelf))) { folio->holder_state |= TXTSW_HOLDER_OF_SHELF; } else { folio->holder_state &= ~TXTSW_HOLDER_OF_SHELF; } } else { folio->holder_state |= TXTSW_HOLDER_OF_ALL; } return(result);}/* Returns TRUE iff function is completely local to textsw, and all * selections are guaranteed to be within the textsw. * The caller should ignore the return value when is_down == TRUE. */pkg_private inttextsw_inform_seln_svc(textsw, function, is_down) register Textsw_folio textsw; register unsigned function; int is_down;{#define ALL_SELECTIONS_ARE_LOCAL(textsw) \ (((textsw)->holder_state & TXTSW_HOLDER_OF_ALL) == TXTSW_HOLDER_OF_ALL) register Seln_function seln_function; if (!textsw_should_ask_seln_svc(textsw, is_down)) { return(TRUE); } switch (function) { case TXTSW_FUNC_DELETE: seln_function = SELN_FN_DELETE; break; case TXTSW_FUNC_FIND: seln_function = SELN_FN_FIND; break; case TXTSW_FUNC_GET: seln_function = SELN_FN_GET; break; case TXTSW_FUNC_PUT: seln_function = SELN_FN_PUT; break; case TXTSW_FUNC_FIELD: /* Seln. Svc. does not (yet) have the concept of FIELD search. */ default: return(TRUE); }#ifdef DEBUG_SVCfprintf(stderr, "Holders: %d Func: %d(%s) ", textsw->holder_state & TXTSW_HOLDER_OF_ALL, (int)function, (is_down) ? "v" : "^");#endif if (is_down) { if (!ALL_SELECTIONS_ARE_LOCAL(textsw)) { textsw_acquire_seln(textsw, SELN_CARET); textsw->selection_func = seln_inform(textsw->selection_client, seln_function, is_down); /* The Seln. Svc. resets the Secondary Selection to be * non-existent on any inform, so make our state agree! */ textsw->holder_state &= ~TXTSW_HOLDER_OF_SSEL; ASSUME(textsw->selection_func.function == SELN_FN_ERROR); textsw->func_state |= TXTSW_FUNC_SVC_SAW(function); } return(TRUE); } else if (textsw->func_state & TXTSW_FUNC_SVC_REQUEST) {#ifdef DEBUG_SVCfprintf(stderr, "Request from service\n");#endif if (textsw->selection_holder == 0 || textsw->selection_holder->state == SELN_NONE || ALL_SELECTIONS_ARE_LOCAL(textsw)) { return(TRUE); } goto Service_Request; } else { if (ALL_SELECTIONS_ARE_LOCAL(textsw) && (textsw->func_state & function) && ((textsw->func_state & TXTSW_FUNC_SVC_SAW_ALL) == 0)) { /* Don't tell svc about UP iff we also had DOWN and * did not tell svc about it. Test for local selections * insures that we would have seen the DOWN. */ return(TRUE); } else { textsw->selection_func = seln_inform(textsw->selection_client, seln_function, is_down);#ifdef DEBUG_SVCfprintf(stderr, "%d\n", textsw->selection_func.function);#endif if (textsw->selection_func.function != SELN_FN_ERROR) { static Seln_response textsw_setup_function(); if (SELN_IGNORE != textsw_setup_function(textsw, &textsw->selection_func)) goto Service_Request; } textsw->func_state &= ~TXTSW_FUNC_EXECUTE; return(FALSE); } }Service_Request:#ifdef DEBUG_SVCfflush(stderr);#endif switch (function) { case TXTSW_FUNC_GET: case TXTSW_FUNC_PUT: return((textsw->selection_holder == 0) || SAME_HOLDER(textsw, (caddr_t)LINT_CAST(textsw->selection_holder))); case TXTSW_FUNC_DELETE: /* Following is required to make DELETEs initiated from another * window work. */ if ((textsw->holder_state & TXTSW_HOLDER_OF_CARET) == 0) textsw->func_state |= TXTSW_FUNC_DELETE; /* Fall through */ default: return(TRUE); }#undef ALL_SELECTIONS_ARE_LOCAL(textsw)}pkg_private inttextsw_abort(textsw) register Textsw_folio textsw;{ if (textsw_should_ask_seln_svc(textsw, TRUE) && (textsw->func_state & TXTSW_FUNC_SVC_SAW_ALL)) { seln_clear_functions(); } if (textsw->track_state & TXTSW_TRACK_SECONDARY) { textsw_set_selection(VIEW_REP_TO_ABS(textsw->first_view), ES_INFINITY, ES_INFINITY, EV_SEL_SECONDARY); } textsw_clear_pending_func_state(textsw); textsw->state &= ~TXTSW_PENDING_DELETE; textsw->track_state &= ~TXTSW_TRACK_ALL;}#ifdef DEBUG_SVCstatic long inform_service = 0x7FFFFFFF;#endifpkg_private voidtextsw_may_win_exit(textsw) Textsw_folio textsw;{#define PENDING_EVENT(textsw, func) \ (((textsw)->func_state & func) && \ (((textsw)->func_state & TXTSW_FUNC_SVC_SAW(func)) == 0)) textsw_flush_caches(textsw->first_view, TFC_STD);#ifdef DEBUG_SVC if (inform_service-- <= 0) return;#endif if (textsw->state & TXTSW_DELAY_SEL_INQUIRE) return; /* Textsw does not know about the state selection svc */ /* * If selection service already got the request, then * it should know about the state. */ if (((textsw->func_state & TXTSW_FUNC_SVC_REQUEST) == 0) && textsw_should_ask_seln_svc(textsw, FALSE)) { unsigned holder_state; Es_index first, last_plus_one; holder_state = textsw->holder_state & TXTSW_HOLDER_OF_ALL; (void) ev_get_selection(textsw->views, &first, &last_plus_one, EV_SEL_SECONDARY); /* Following makes sure cache actually tells the svc. */ textsw->holder_state &= ~TXTSW_HOLDER_OF_ALL; if (PENDING_EVENT(textsw, TXTSW_FUNC_DELETE)) (void) textsw_inform_seln_svc(textsw, TXTSW_FUNC_DELETE, TRUE); if (PENDING_EVENT(textsw, TXTSW_FUNC_FIND)) (void) textsw_inform_seln_svc(textsw, TXTSW_FUNC_FIND, TRUE); if (PENDING_EVENT(textsw, TXTSW_FUNC_GET)) (void) textsw_inform_seln_svc(textsw, TXTSW_FUNC_GET, TRUE); if (PENDING_EVENT(textsw, TXTSW_FUNC_PUT)) (void) textsw_inform_seln_svc(textsw, TXTSW_FUNC_PUT, TRUE); /* Restore the cache's state, and sync Seln. Svc. - sticky part * is we had not told Svc. about key down and may be part way * into 2nd-ary Seln., which we also have not told Svc. about. */ textsw->holder_state |= holder_state; textsw->holder_state &= ~TXTSW_HOLDER_OF_SSEL; if (first < last_plus_one) { textsw_acquire_seln(textsw, SELN_SECONDARY); } }#undef PENDING_EVENT}/* Returns new value for buf_max_len. * Can alter to_read and buf as side_effects. */pkg_private inttextsw_prepare_buf_for_es_read(to_read, buf, buf_max_len, fixed_size) register int *to_read; register char **buf; register int buf_max_len; int fixed_size;{ if (*to_read > buf_max_len) { if (fixed_size) { *to_read = buf_max_len; } else { free(*buf); buf_max_len = *to_read+1; *buf = sv_malloc((u_int)buf_max_len); } } return(buf_max_len);}/* Returns the actual number of entities read into the buffer. * Caller is responsible for making sure that the buffer is large enough. */pkg_private inttextsw_es_read(esh, buf, first, last_plus_one) register Es_handle esh; register char *buf; Es_index first; register Es_index last_plus_one;{ register int result; int count; register Es_index current, next; result = 0; current = first; (void) es_set_position(esh, current); while (last_plus_one > current) { next = es_read(esh, last_plus_one-current, buf+result, &count); if READ_AT_EOF(current, next, count) break; result += count; current = next; } return(result);}typedef struct tsfh_object { Textsw_view view; Textsw_selection_handle selection; Seln_attribute continued_attr; unsigned flags; int fill_result;} Tsfh_object;typedef Tsfh_object *Tsfh_handle;pkg_private inttextsw_fill_selection_from_reply(context, reply) register Tsfh_handle context; register Seln_request *reply;{ int result = 0; register caddr_t *attr; int got_contents_ascii = FALSE, to_read; register Textsw_selection_handle selection = context->selection; if (context->continued_attr != SELN_REQ_END_REQUEST) { return(TFS_ERROR); } for (attr = (caddr_t *)LINT_CAST(reply->data); *attr; attr = attr_next(attr)) { switch ((Seln_attribute)(*attr)) { case SELN_REQ_BYTESIZE: selection->first = 0; selection->last_plus_one = (Es_index)attr[1]; break; case SELN_REQ_FIRST: selection->first = (Es_index)attr[1]; break; case SELN_REQ_LAST: selection->last_plus_one = 1 + (Es_index)attr[1]; break; case SELN_REQ_CONTENTS_ASCII: if (reply->status == SELN_CONTINUED) { context->continued_attr = (Seln_attribute)(*attr); to_read = strlen((char *)(attr+1)); } else { to_read = selection->last_plus_one - selection->first; } selection->buf_max_len = textsw_prepare_buf_for_es_read(&to_read, &selection->buf, selection->buf_max_len, !selection->buf_is_dynamic); selection->buf_len = to_read; /* Clients must be aware that either due to continuation * or because the buffer was not big enough, * selection->last_plus_one may be greater than * selection->first + to_read */ bcopy((char *)(attr+1), selection->buf, to_read); got_contents_ascii = TRUE; if (reply->status == SELN_CONTINUED) goto Return; break; case SELN_REQ_UNKNOWN: result |= TFS_BAD_ATTR_WARNING; break; default: if ((attr == (caddr_t *)LINT_CAST(reply->data)) || ((context->flags & TFS_FILL_IF_OTHER) && (got_contents_ascii == FALSE))) goto Seln_Error; result |= TFS_BAD_ATTR_WARNING; break; } }Return: return(result);Seln_Error: return(TFS_SELN_SVC_ERROR);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -