📄 sel_clnt.c
字号:
#ifndef lint#ifdef sccsstatic char sccsid[] = "@(#)sel_clnt.c 1.1 92/07/30";#endif#endif#include <varargs.h>#include <sunwindow/rect.h> /* LINT_CAST definition */#include <suntool/selection_impl.h>/* * Sel_clnt: client (selection-holder) routines for talking * to the selection service, and to other holders. * * There may be several selections active at a time, distinguished by * their "rank" (primary, secondary, shelf). * * Terminology: The old service / client distinction doesn't work too * well here, since the real service does very little, and the "clients" * may both make and respond to calls symmetrically. So: * The clearinghouse process that helps application programs get in * touch with each other, and maintains the state of the user interface, * is the "service". * The remainder of this process (outside the selection routines) * is the "client." * A process (this or another) that currently holds a selection * is a "holder"; * a process that wants to communicate with a holder about the selection * is a "requester." */typedef enum { Seln_seized_self, Seln_seized_ok, Seln_seized_blind} Seln_seize_result;/* * How we get in touch with the server: */static CLIENT *service;static int service_socket;static Seln_holder service_holder;/* * Procedures */static int seln_init_holder_process();static void seln_client_remove(), seln_dispatch(), seln_update_service();static Seln_result seln_get_access(), seln_get_service_holder(), seln_local_request();static Seln_holder seln_holder_of_rank();static Seln_seize_result seln_seize();static CLIENT *seln_get_service();/* * External procedures (called by our client) * * * Create: generate & store client identification; initialize per-process * information (socket, service transport handle, ...) if this is the first * client. */char *seln_create(function_proc, request_proc, client_data) void (*function_proc)(); Seln_result (*request_proc)(); char *client_data;{ register Seln_client_node *handle; extern char *malloc(); static unsigned num_of_clients; /* incremented each time a new client calls * seln_create. So each client has a unique * id for varification of existence. */ if (clients.next == (Seln_client_node *) NULL) { if (!seln_init_holder_process()) { return (char *) NULL; } } if ((handle = (Seln_client_node *) (LINT_CAST( malloc((unsigned)(sizeof(Seln_client_node)))))) == (Seln_client_node *) NULL) { return (char *) NULL; } handle->client_num = ++num_of_clients; handle->ops.do_function = function_proc; handle->ops.do_request = request_proc; handle->access = seln_my_access; handle->access.client = (char *)handle; handle->client_data = client_data; handle->next = clients.next; clients.next = handle; return (char *) handle;}/* Destroy: destroy a client instance; if that was the last client in * this process, shut down everything else. */voidseln_destroy(client) char *client;{ int i; if (client == (char *)NULL) { (void)fprintf(stderr, "Selection library asked to destroy a 0 client.\n"); return; } for (i = 1; i < SELN_RANKS; i++) { (void) seln_done(client, (Seln_rank) i); } seln_client_remove((Seln_client_node *)(LINT_CAST(client))); if (clients.next == NULL) { (void) notify_set_input_func((Notify_client) seln_my_udp_transport, NOTIFY_FUNC_NULL, seln_my_udp_socket); svc_destroy(seln_my_udp_transport); (void)close(seln_my_udp_socket); (void) notify_set_input_func((Notify_client) seln_my_tcp_transport, NOTIFY_FUNC_NULL, seln_my_tcp_socket); svc_destroy(seln_my_tcp_transport); (void)close(seln_my_tcp_socket); clnt_destroy(service); (void)close(service_socket); }}/* Next batch are calls to the selection service * * Acquire: acquire the indicated selection. * (The client may pass in SELN_UNSPECIFIED; this means acquire the * secondary selection if a function key is down, else the primary.) * Return the socket on which to listen for RPC requests; NULL on failure. */Seln_rankseln_acquire(seln_client, asked) Seln_client seln_client; Seln_rank asked;{ Seln_rank given; Seln_result result; Seln_holder buffer; enum clnt_stat status; Seln_client_node *client; client = (Seln_client_node *)(LINT_CAST(seln_client)); if (client == (Seln_client_node *)NULL) { complain("Acquire for a null client"); return SELN_UNKNOWN; } /* Determine which if unspecified; take it from current holder if any */ if (seln_seize(client->client_data, asked, &given) == Seln_seized_self) { return given; } /* Tell the service we're it now */ buffer.rank = given; buffer.state = SELN_EXISTS; buffer.access = client->access; status = clnt_call(service, SELN_SVC_ACQUIRE, xdr_seln_holder, &buffer, xdr_enum, &result, seln_std_timeout); if (status != RPC_SUCCESS) { clnt_perror(service, "Couldn't inform service we hold selection"); return SELN_UNKNOWN; } if (result != SELN_SUCCESS) { complain("Service wouldn't let us acquire selection"); (void)fprintf(stderr, "requested selection: %d; result: %d\n", given, result); return SELN_UNKNOWN; } return given;}/* * Tell the service we're giving up the selection (e.g. on termination) */Seln_resultseln_done(seln_client, rank) Seln_client seln_client; Seln_rank rank;{ Seln_holder my_descriptor; Seln_result result; Seln_client_node *client; client = (Seln_client_node *)(LINT_CAST(seln_client)); if (client == (Seln_client_node *)NULL) { complain("Done for a null client"); return SELN_FAILED; } my_descriptor.rank = rank; my_descriptor.access = client->access; if (clnt_call(service, SELN_SVC_DONE, xdr_seln_holder, &my_descriptor, xdr_enum, &result, seln_std_timeout) != RPC_SUCCESS) { clnt_perror(service, "Couldn't reach service to yield selection"); return SELN_FAILED; } return result;}/* * We want the service to take over as holder of a selection * whose contents are stored in a file. */Seln_resultseln_hold_file(rank, path) Seln_rank rank; char *path;{ Seln_file_info buffer; Seln_result result; if (service == (CLIENT *) NULL) { if ((service = seln_get_service(&service_socket)) == (CLIENT *)NULL) { return SELN_FAILED; } } buffer.rank = rank; buffer.pathname = path; if (clnt_call(service, SELN_SVC_HOLD_FILE, xdr_seln_file_info, &buffer, xdr_enum, &result, seln_std_timeout) != RPC_SUCCESS) { clnt_perror(service, "Couldn't ask service to hold a file for us"); return SELN_FAILED; } return result;}/* * Get rid of any selections this process holds */voidseln_yield_all(){ register int i; union { Seln_holder array[SELN_RANKS]; struct { Seln_holder first; Seln_holders_all rest; } rec; } holders; holders.rec.rest = seln_inquire_all(); for (i = ord(SELN_CARET); i <= ord(SELN_SHELF); i++) { if (holders.array[i].state == SELN_EXISTS && seln_holder_same_process(&holders.array[i])) { (void)seln_send_yield((Seln_rank) i, &holders.array[i], TRUE); seln_update_service((Seln_rank) i); } }}/* * We saw a function key change state; tell the service. */Seln_function_bufferseln_inform(seln_client, which, down) Seln_client seln_client; Seln_function which; int down;{ Seln_inform_args buffer; Seln_function_buffer result; Seln_client_node *client; client = (Seln_client_node *)(LINT_CAST(seln_client)); if (service == (CLIENT *) NULL) { return seln_null_function; } buffer.holder.rank = SELN_UNKNOWN; buffer.holder.state = SELN_NONE; if (client == (Seln_client_node *) NULL) { bzero((char *)(LINT_CAST(&buffer.holder.access)), sizeof(Seln_access)); } else { buffer.holder.access = client->access; } buffer.function = which; buffer.down = down; result.addressee_rank = SELN_UNKNOWN; if (clnt_call(service, SELN_SVC_INFORM, xdr_seln_inform_args, &buffer, xdr_seln_function, &result, seln_std_timeout) != RPC_SUCCESS) { clnt_perror(service, "Couldn't tell service function key has changed"); } return result;}/* * functions_state: ask service for state of all function-keys */Seln_resultseln_functions_state(result) Seln_functions_state *result;{ if (service == (CLIENT *)NULL) { if ((service = seln_get_service(&service_socket)) == (CLIENT *)NULL) { return SELN_FAILED; } } if (clnt_call(service, SELN_SVC_FUNCTIONS_ALL, xdr_void, 0, xdr_seln_functions_state, result, seln_std_timeout) != RPC_SUCCESS) { clnt_perror(service, "Couldn't ask service who holds selection"); return SELN_FAILED; } return SELN_SUCCESS;}/* * get_function_state: ask the service whether a function key is down */seln_get_function_state(func) Seln_function func;{ u_int result; if (service == (CLIENT *)NULL) { if ((service = seln_get_service(&service_socket)) == (CLIENT *)NULL) { return 0; } } if (clnt_call(service, SELN_SVC_FUNCTION_ONE, xdr_enum, &func, xdr_int, &result, seln_std_timeout) != RPC_SUCCESS) { clnt_perror(service, "Couldn't ask service who holds selection"); return 0; } return result;}/* * Inquire: ask the service for access info for the holder of * the indicated selection. (Again, UNSPECIFIED means * PRIMARY or SECONDARY as appropriate.) */Seln_holderseln_inquire(which) Seln_rank which;{ Seln_holder result; if (service == (CLIENT *)NULL) { if ((service = seln_get_service(&service_socket)) == (CLIENT *)NULL) { return seln_null_holder; } } if (clnt_call(service, SELN_SVC_INQUIRE, xdr_enum, &which, xdr_seln_holder, &result, seln_std_timeout) != RPC_SUCCESS) { clnt_perror(service, "Couldn't ask service who holds selection"); return seln_null_holder; } return result;}/* * Inquire_all: ask the service for access info for the holders of * all selections. */Seln_holders_allseln_inquire_all(){ Seln_holders_all result; if (service == (CLIENT *) NULL) { if ((service = seln_get_service(&service_socket)) == (CLIENT *) NULL) { result.caret = result.primary = result.secondary = result.shelf = seln_null_holder; return result; } } if (clnt_call(service, SELN_SVC_INQUIRE_ALL, xdr_void, 0, xdr_seln_holders_all, &result, seln_std_timeout) != RPC_SUCCESS) { clnt_perror(service, "Couldn't ask service for selection holders"); result.caret = result.primary = result.secondary = result.shelf =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -