⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 textsw_filter.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lint#ifdef sccsstatic	char sccsid[] = "@(#)textsw_filter.c 1.1 92/07/30";#endif#endif/* * Copyright (c) 1986 by Sun Microsystems, Inc. *//* * Filter invocation routines for textsw package. */#include <suntool/primal.h>#include <suntool/textsw_impl.h>#include <fcntl.h>#include <signal.h>#include <vfork.h>#include <sys/errno.h>#include <sys/ioctl.h>#define FAIL		-1#define	INPUT		0#define	OUTPUT		1#define	STDIN		0#define	STDOUT		1#define	STDERR		2#define	PIPSIZ		4096		/* See uipc_pipe.c */#define	SLOP_SIZE	16#define	REPLY_ERROR	-1#define	REPLY_OKAY	 0#define	REPLY_SEND	 1/* performance: global cache of getdtablesize() */extern int dtablesize_cache;#define GETDTABLESIZE() \	(dtablesize_cache?dtablesize_cache:(dtablesize_cache=getdtablesize()))extern int		 errno;extern char		*getlogindir();pkg_private Es_index	 textsw_do_input();static short unsigned	 type_for_filter_rec();static int		 event_code_for_filter_rec();/* WARNING: this is a hack to force the variable to be in memory. *	this var gets changed somehow when it is in register in the *	context of a vfork(); */static int		 execvp_failed;pkg_private Ev_mark_object	textsw_add_mark_internal();extern Notify_value		notify_default_wait3();static intinterpret_filter_reply(view, buffer, buffer_length, delta)	Textsw_view	 view;	char		*buffer;	int		 buffer_length;	Es_index	*delta;{	*delta = textsw_do_input(view, buffer, (long)buffer_length, 	                         TXTSW_UPDATE_SCROLLBAR_IF_NEEDED);	if AN_ERROR(*delta != buffer_length)	    return(REPLY_ERROR);	return(REPLY_OKAY);}/* * Ignores SIGPIPE so that write(2) to nonexistent or dead filter *  does not cause parent (containing textsw) to terminate. *//* ARGSUSED */static Notify_valuetextsw_sigpipe_func(textsw, sig, mode)	Textsw_folio		textsw;		/* Currently unused */	int			sig;		/* Currently unused */	Notify_signal_mode	mode;		/* Currently unused */{	return(NOTIFY_DONE);}static inttextsw_filter_selection(folio, fill_in)	register Textsw_folio			folio;	register Textsw_selection_handle	fill_in;/* Note: this routine guarantees to return a valid (but possibly empty) *	selection, thus callers need not error check the return value. */{	textsw_init_selection_object(folio, fill_in, "", 0, FALSE);	fill_in->type = textsw_func_selection_internal(					folio, fill_in, EV_SEL_PRIMARY, 0);	if (TFS_IS_ERROR(fill_in->type) || (fill_in->type & TFS_IS_OTHER)) {	    fill_in->last_plus_one = fill_in->first = ES_INFINITY;	    fill_in->type = EV_SEL_PRIMARY | TFS_IS_SELF;	}	if (fill_in->first < fill_in->last_plus_one) {	    textsw_set_selection(VIEW_REP_TO_ABS(folio->first_view),				 ES_INFINITY, ES_INFINITY,				 (unsigned) fill_in->type);	} else {	    fill_in->type &= ~EV_SEL_PENDING_DELETE;	}	return(fill_in->type);}pkg_private inttextsw_call_filter(view, filter_argv)	register Textsw_view	 view;	char			*filter_argv[];{	register Textsw_folio	 folio = FOLIO_FOR_VIEW(view);	int			 filter_input, filter_output,				 result = 0;	Es_index		 save_length;	Ev_mark_object		 save_lpo_id;	Ev_mark_object		 save_insert = NULL;	int			 pid;	Textsw_selection_object	 selection;	Notify_func		 old_sigpipe = (Notify_func)0;	Es_index		 ev_get_insert();	(void) textsw_filter_selection(folio, &selection);	if (selection.type & EV_SEL_PENDING_DELETE) {	    save_length = selection.last_plus_one - selection.first;	    save_lpo_id =		textsw_add_mark_internal(folio, selection.last_plus_one,					 TEXTSW_MARK_DEFAULTS);	}	pid = start_filter(filter_argv, &filter_input, &filter_output);	if (pid == FAIL) {	    result = 1;	    goto NoFilterReturn;	}	ev_set(0, folio->views, EV_CHAIN_DELAY_UPDATE, TRUE, 0);	if ((int) ev_get(folio->views, EV_CHAIN_LOWER_CONTEXT)	    != EV_NO_CONTEXT)	    save_insert = textsw_add_mark_internal(folio,				     ev_get_insert(folio->views),				     TEXTSW_MARK_MOVE_AT_INSERT);	old_sigpipe =	    notify_set_signal_func((Notify_client)folio, textsw_sigpipe_func,				   SIGPIPE, NOTIFY_ASYNC);	(void) notify_set_wait3_func((Notify_client)folio,				     notify_default_wait3, pid);	    /* Note that there is no meaningful old_wait3_func */	switch (talk_to_filter(view, filter_input, filter_output,			       selection.first, selection.last_plus_one,			       interpret_filter_reply)) {	  case 0:	    break;	  case 1:	    goto ErrorReturn;	}NormalReturn:	(void) close(filter_output);	if ((result == 0) && (selection.type & EV_SEL_PENDING_DELETE)) {	    Es_index		saved_lpo;	    saved_lpo = textsw_find_mark_internal(folio, save_lpo_id);	    if AN_ERROR(saved_lpo == ES_INFINITY) {	    } else {		(void) textsw_delete_span(view, saved_lpo-save_length,					  saved_lpo,					  TXTSW_DS_ADJUST|TXTSW_DS_SHELVE);	    }	}	if (old_sigpipe)	    (void) notify_set_signal_func((Notify_client)folio, old_sigpipe,					  SIGPIPE, NOTIFY_ASYNC);NoFilterReturn:        (void) close(filter_input); /* ECD fix */        (void) close(filter_output); /* ECD fix */	if (selection.type & EV_SEL_PENDING_DELETE)	    textsw_remove_mark_internal(folio, save_lpo_id);	/* Complete the deferred display update and autoscroll. */	ev_set(0, folio->views, EV_CHAIN_DELAY_UPDATE, FALSE, 0);	ev_update_chain_display(folio->views);	textsw_do_insert_makes_visible(view);	if (save_insert) {	    ev_scroll_if_old_insert_visible(folio->views,		textsw_find_mark_internal(folio, save_insert),		/* Assign delta to minimum to ensure correct behavior,		 * may not be optimal.		 */		1);	    textsw_remove_mark_internal(folio, save_insert);	}	return(result);ErrorReturn:	result = 2;	goto NormalReturn;}static inttalk_to_filter(view, filter_input, filter_output, first, last_plus_one,	       interpret_reply)	register Textsw_view	  view;	int			  filter_input, filter_output;	register Es_index	  first, last_plus_one;	int			(*interpret_reply)();{#define	NR_FIRST		0#define	NR_LAST_PLUS_ONE	1	extern Es_index		  ev_get_insert();	register Textsw_folio	  folio = FOLIO_FOR_VIEW(view);	int			  max_fds = GETDTABLESIZE(),				  nr_valid = 0,				  status,				  result = 0;	unsigned long		  buffer_and_slop[(PIPSIZ+SLOP_SIZE)/						  sizeof(unsigned long)];	unsigned char		 *buffer;	struct timeval		  tv;	Es_index		  insert, next_request[2];	/* buffer_and_slop is declared unsigned long in order to meet the	 * most restrictive of the alignment restrictions.	 */	buffer = (unsigned char *)LINT_CAST(buffer_and_slop) + SLOP_SIZE;	/*	 * Copy data into the filter.  As filter makes the filtered	 *   data available, copy it to output_file.	 * Stdio is not used to read from the filter because it is necessary	 *   to make sure that the read does not block.  In addition, for both	 *   reading and writing of the filter, the stdio automatic buffering	 *   is only a hinderance.	 */	for (;;) {	    register int		 nfds;	    fd_set			 exceptfds, readfds, writefds;	    long int			 written[3];	    FD_ZERO(&exceptfds); FD_ZERO(&readfds); FD_ZERO(&writefds);	    FD_SET(filter_output, &readfds);	    if (first < last_plus_one) {		/* writefds |= (1 << filter_input); */		FD_SET(filter_input, &writefds);	    } else {		/* For a "dumb" filter, we must close the input so that it		 *   does not hang waiting for more of the selection from us.		 */		if (interpret_reply == interpret_filter_reply) {		    (void) close(filter_input);		    filter_input = -1;		}	    }	    /* Filter only has tv.tv_sec seconds to reply, or we assume it	     *   is permanently hung.	     * BUG ALERT! This should be customizable by user and/or client.	     */	    tv.tv_sec = 15; tv.tv_usec = 0;	    nfds = select(max_fds, &readfds, &writefds, &exceptfds, &tv);	    switch (nfds) {	      case -1:	if (errno == EINTR)			    continue;		/* Probably itimer expired */			goto ErrorReturn;	      case 0:	goto ErrorReturn;	/* Assume filter has hung */	      default:	break;	    }	    /* if (readfds & (1 << filter_output)) { */	    if (FD_ISSET(filter_output, &readfds)) {		register int	bytes_read;		bytes_read = read(filter_output, (char *)buffer,				  sizeof(buffer_and_slop)-SLOP_SIZE);		switch (bytes_read) {		  case 0:		    if (first >= last_plus_one)		        goto NormalReturn;		    break;		  case -1:		    if (errno == EINTR)			break;			/* Probably itimer expired */		    goto ErrorReturn;		  default:		    insert = ev_get_insert(folio->views);		    status = interpret_reply(view, buffer, bytes_read,					     &written[0]);		    switch (status) {		      case REPLY_ERROR:			goto ErrorReturn;		      case REPLY_OKAY:			break;		      case REPLY_SEND:			if AN_ERROR(nr_valid != 0) {			} else {			    nr_valid = 1;			    next_request[NR_FIRST] = written[1];			    next_request[NR_LAST_PLUS_ONE] = written[2];			}			break;		    }		    if (insert <= first) {			first += written[0];			last_plus_one += written[0];		    }		    break;		}	    	    } 	    	    /*  if (writefds & (1 << filter_input)) { */	    if (FD_ISSET(filter_input, &writefds)) {		int		to_write;		Es_index	next;		(void) es_set_position(folio->views->esh, first);		to_write = sizeof(buffer_and_slop) - SLOP_SIZE;		if (to_write > last_plus_one-first)		    to_write = last_plus_one-first;		next = es_read(folio->views->esh, to_write, buffer, &to_write);		if (READ_AT_EOF(first, next, to_write)) {		    first = last_plus_one;		} else {		    ASSUME(to_write <= PIPSIZ);		    written[0] = write(filter_input, (char *)buffer, to_write);		    if (written[0] == -1) {			if (errno == EWOULDBLOCK) {			    /* Go around and wait for filter to run */			} else goto ErrorReturn;		    } else {			if (written[0] < to_write) 			    next = (first + written[0]);			     			first = next;		    }		}	    }	    if (first >= last_plus_one) {		if (nr_valid != 0) {		    first = next_request[NR_FIRST];		    last_plus_one = next_request[NR_LAST_PLUS_ONE];		    nr_valid = 0;		}	    }	}NormalReturn:	if (filter_input != -1)	    (void) close(filter_input);	return(result);ErrorReturn:	result = 1;	goto NormalReturn;#undef	NR_FIRST#undef	NR_LAST_PLUS_ONE}static intsmarter_interpret_filter_reply(view, buffer, buffer_length, delta)	Textsw_view		 view;	register char		*buffer;	int			 buffer_length;	Es_index		*delta;{	register Textsw_folio	 folio = FOLIO_FOR_VIEW(view);	char			*save_buffer = buffer;	register char		*buffer_last_plus_one;	int			*int_buffer;	int			 result = REPLY_OKAY;	/* First deal with old stuff that is left over */	if (folio->owed_by_filter < 0) {	    bcopy(buffer, buffer-SLOP_SIZE-folio->owed_by_filter,		  buffer_length);	    buffer_length -= folio->owed_by_filter;	    buffer -= SLOP_SIZE;	    folio->owed_by_filter = 0;	}	buffer_last_plus_one = buffer + buffer_length;	/* Process the requests from the filter */	while (buffer < buffer_last_plus_one) {	    if (folio->owed_by_filter > 0) {		int	 to_insert = folio->owed_by_filter;		if (to_insert > buffer_last_plus_one-buffer)		    to_insert = buffer_last_plus_one-buffer;		*delta = textsw_do_input(view, buffer, (long)to_insert,					 TXTSW_UPDATE_SCROLLBAR_IF_NEEDED);		if AN_ERROR(*delta != to_insert)		    return(REPLY_ERROR);		folio->owed_by_filter -= to_insert;		buffer += ((to_insert+sizeof(int)-1)/sizeof(int))*sizeof(int);		continue;	    }	    int_buffer = (int *)LINT_CAST(buffer);	    if ((buffer_last_plus_one-buffer < 2*sizeof(int)) ||		((int_buffer[0]) != TEXTSW_FILTER_MAGIC))		goto Deal_With_Slop;	    switch ((Textsw_filter_command)(int_buffer[1])) {	      case TEXTSW_FILTER_DELETE_RANGE:		if (buffer_last_plus_one-buffer < 4*sizeof(int))		    goto Deal_With_Slop;		*delta = textsw_delete_span(view, (long)int_buffer[2],					    (long)int_buffer[3],					    TXTSW_DS_ADJUST|TXTSW_DS_SHELVE);		buffer += 4*sizeof(int);		break;	      case TEXTSW_FILTER_INSERT:		if (buffer_last_plus_one-buffer < 3*sizeof(int))		    goto Deal_With_Slop;		folio->owed_by_filter = int_buffer[2];		buffer += 3*sizeof(int);		break;	      case TEXTSW_FILTER_SEND_RANGE: {		if (buffer_last_plus_one-buffer < 4*sizeof(int))		    goto Deal_With_Slop;		delta[1] = int_buffer[2];		delta[2] = int_buffer[3];		result = REPLY_SEND;		buffer += 4*sizeof(int);		break;	      }	      case TEXTSW_FILTER_SET_INSERTION:		if (buffer_last_plus_one-buffer < 3*sizeof(int))		    goto Deal_With_Slop;		(void) ev_set_insert(folio->views, (Es_index)int_buffer[2]);		buffer += 3*sizeof(int);		break;	      case TEXTSW_FILTER_SET_SELECTION:		if (buffer_last_plus_one-buffer < 4*sizeof(int))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -