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

📄 cmdsw_notify.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lint#ifdef sccsstatic	char sccsid[] = "@(#)cmdsw_notify.c 1.1 92/07/30";#endif#endif/* * Copyright (c) 1988 by Sun Microsystems, Inc. *//* * Notifier related routines for the cmdsw. */#include <sys/types.h>#include <sys/file.h>#include <sys/time.h>#include <sys/resource.h>#include <sys/wait.h>#include <sgtty.h>#include <signal.h>#include <stdio.h>#include <ctype.h>#include <pixrect/pixrect.h>#include <pixrect/pixfont.h>#include <sunwindow/notify.h>#include <sunwindow/rect.h>#include <sunwindow/rectlist.h>#include <sunwindow/pixwin.h>#include <sunwindow/win_input.h>#include <sunwindow/win_notify.h>#include <suntool/ttysw.h>#include <suntool/window.h>#include <suntool/frame.h>#include <suntool/alert.h>#include <suntool/ttysw_impl.h>extern Textsw	  textsw_first();extern Textsw	  textsw_next();extern caddr_t	  textsw_get();extern int	  textsw_default_notify();extern char	  *textsw_checkpoint_undo();extern Textsw_index	textsw_insert();extern Textsw_status	textsw_set();extern Textsw_index	textsw_erase();extern void		textsw_display();extern Notify_value	ttysw_text_input_pending();extern void		ttysw_sigwinch();extern void		ttysw_sendsig();extern Cmdsw	*cmdsw;#ifdef DEBUG#define ERROR_RETURN(val)	abort();	/* val */#else#define ERROR_RETURN(val)	return(val);#endif DEBUG/* performance: global cache of getdtablesize() */extern int dtablesize_cache;#define GETDTABLESIZE() \	(dtablesize_cache?dtablesize_cache:(dtablesize_cache=getdtablesize()))/* shorthand - Duplicate of what's in ttysw_main.c */#define	iwbp	ttysw->ttysw_ibuf.cb_wbp#define	iebp	ttysw->ttysw_ibuf.cb_ebp#define	ibuf	ttysw->ttysw_ibuf.cb_buf/* Pkg_private */ Notify_valuettysw_text_destroy(textsw, status)    register Textsw     textsw;    Destroy_status        status;{    Ttysw              *ttysw;    Notify_value	nv = NOTIFY_IGNORED;    int			last_view;        /* WARNING: call on notify_next_destroy_func invalidates textsw,     *	and thus the information about the textsw must be extracted first.     */    last_view = (textsw_next(textsw_first(textsw)) == (Textsw) 0);    ttysw = (Ttysw *)LINT_CAST(textsw_get(textsw, TEXTSW_CLIENT_DATA));	/* WARNING: ttysw may be NULL */    if (status == DESTROY_CHECKING) {        return (NOTIFY_IGNORED);    } else {	nv = notify_next_destroy_func((Notify_client)(LINT_CAST(textsw)), status);    }    if (last_view && ttysw) {	nv = ttysw_destroy(ttysw, status);    }    return nv;}static Textsw_indexfind_and_remove_mark(textsw, mark)    Textsw		textsw;    Textsw_mark		mark;{    Textsw_index	result;    result = textsw_find_mark(textsw, mark);    if (result != TEXTSW_INFINITY)	textsw_remove_mark(textsw, mark);    return(result);}/* Pkg_private */ voidttysw_move_mark(textsw, mark, to, flags)    Textsw		 textsw;    Textsw_mark		*mark;    Textsw_index	 to;    int			 flags;{    textsw_remove_mark(textsw, *mark);    *mark = textsw_add_mark(textsw, to, (unsigned)flags);}/* Pkg_private */ Notify_valuettysw_text_event(textsw, event, arg, type)    register Textsw	  textsw;    Event                *event;    Notify_arg     	  arg;    Notify_event_type     type;{    Ttysw		*ttysw;    int			 insert = TEXTSW_INFINITY;    int			 length = TEXTSW_INFINITY;    int			 cmd_start;    int			 did_map = 0;    Notify_value	 nv = NOTIFY_IGNORED;    Menu		 textsw_menu, cmd_modes_menu;    Menu_item		 scroll_cmd, cmd_modes_item;    int			 action = (cmdsw->cooked_echo ? event_action(event) : event_id(event));    ttysw = (Ttysw *)LINT_CAST(textsw_get(textsw, TEXTSW_CLIENT_DATA));        if ((action == MS_RIGHT) && event_is_down(event)) {    /*     * To ensure the textsw from MENU_CLIENT_DATA is one where the     * menu come up, instead of the one the menu is created from.     *     **In SV3.4 and later, the menu structure has been modified so that     * the last cmd in the menu is a pullright menu with the previous     * two cmds nested within it.     */        textsw_menu = (Menu)textsw_get(textsw, TEXTSW_MENU);  /* top level */        /* The reason for using menu_get() is menu_find() has problem. */	cmd_modes_item = (Menu_item)menu_get(	  textsw_menu,	  MENU_NTH_ITEM,	  menu_get(textsw_menu, MENU_NITEMS, 0));        cmd_modes_menu = (Menu)menu_get(	  cmd_modes_item,	  MENU_PULLRIGHT,	  0);        scroll_cmd = (Menu_item)menu_get(	  cmd_modes_menu,	  MENU_NTH_ITEM,	  menu_get(cmd_modes_menu, MENU_NITEMS, 0));         			        (void)menu_set(scroll_cmd, MENU_CLIENT_DATA, textsw, 0);    }            if (!ttysw_getopt((caddr_t)ttysw, TTYOPT_TEXT)) {	nv = notify_next_event_func((Notify_client)(LINT_CAST(textsw)), 		(Notify_event)(LINT_CAST(event)), arg, type);        return (nv);    }        if (cmdsw->cooked_echo    && (cmdsw->cmd_started == 0)    && (insert = (int)textsw_get(textsw, TEXTSW_INSERTION_POINT))    == (length = (int)textsw_get(textsw, TEXTSW_LENGTH))) {   		(void)textsw_checkpoint_again(textsw);    }    if (cmdsw->cooked_echo    &&  cmdsw->cmd_started    &&  cmdsw->literal_next    &&  action <= ASCII_LAST    && (insert = (int)textsw_get(textsw, TEXTSW_INSERTION_POINT))    == (length = (int)textsw_get(textsw, TEXTSW_LENGTH))) {  		char	input_char = (char)action;		textsw_replace_bytes(textsw, length-1, length, &input_char, 1);		cmdsw->literal_next = FALSE;		return NOTIFY_DONE;    }    /* ^U after prompt, before newline should only erase back to prompt. */    if (cmdsw->cooked_echo    &&  event_id(event) == (short)cmdsw->erase_line    &&  event_is_down(event)    && !event_shift_is_down(event)    &&  cmdsw->cmd_started != 0    &&  ((insert = (int)textsw_get(textsw, TEXTSW_INSERTION_POINT))) >        (cmd_start = (int)textsw_find_mark(textsw, cmdsw->user_mark))) {        int			pattern_start = cmd_start;        int			pattern_end = cmd_start;        char			newline = '\n';        if (textsw_find_bytes(            textsw, (long *)&pattern_start, (long *)&pattern_end,            &newline, 1, 0) == -1        || (pattern_start <= cmd_start || pattern_start >= (insert-1))) {	    (void)textsw_erase(textsw,	        (Textsw_index)cmd_start, (Textsw_index)insert);	    return NOTIFY_DONE;        }    }    if (!cmdsw->cooked_echo    &&  (action == '\r'|| action == '\n')    &&  (event->ie_shiftmask & CTRLMASK)    &&  (win_get_vuid_value(ttysw->ttysw_wfd, 'm') == 0)    &&  (win_get_vuid_value(ttysw->ttysw_wfd, 'j') == 0)    &&  (win_get_vuid_value(ttysw->ttysw_wfd, 'M') == 0)    &&  (win_get_vuid_value(ttysw->ttysw_wfd, 'J') == 0) ) {		/* Implement "go to end of file" ourselves. */		/* First let textsw do it to get at normalize_internal. */		nv = notify_next_event_func((Notify_client)(LINT_CAST(textsw)), 			(Notify_client)(LINT_CAST(event)), arg, type);	/* Now fix it up.	 * Only necessary when !append_only_log because otherwise	 * the read-only mark at INFINITY-1 gets text to implement	 * this function for us.	 */	if (!cmdsw->append_only_log)	    (void)textsw_set(textsw, TEXTSW_INSERTION_POINT,		       textsw_find_mark(textsw, cmdsw->pty_mark), 0);    } else if (!cmdsw->cooked_echo    &&  action <= ASCII_LAST     &&  (iscntrl((char)action) || (char)action == '\177')    &&  (insert = (int)textsw_get(textsw, TEXTSW_INSERTION_POINT))    ==  textsw_find_mark(textsw, cmdsw->pty_mark)) {   		/* In !cooked_echo, ensure textsw doesn't gobble up control chars */		char	input_char = action;					(void)textsw_insert(textsw, &input_char, (long) 1);		nv = NOTIFY_DONE;    } else if (cmdsw->cooked_echo    &&  action == cmdsw->tchars.t_stopc) {   		/* implement flow control characters as page mode */		(void) ttysw_freeze(ttysw, 1);    } else if (cmdsw->cooked_echo    &&  action == cmdsw->tchars.t_startc) {  		(void) ttysw_freeze(ttysw, 0);		(void) ttysw_reset_conditions(ttysw);    } else if (!cmdsw->cooked_echo    ||  action != (short)cmdsw->tchars.t_eofc) {		/* Nice normal event */		nv = notify_next_event_func((Notify_client)(LINT_CAST(textsw)), 			(Notify_event)(LINT_CAST(event)), arg, type);    }       if (nv == NOTIFY_IGNORED) {		if ((action > META_LAST) &&		    (action < LOC_MOVE || action > WIN_UNUSED_15)) {		    did_map = (ttysw_domap(ttysw, event) == TTY_DONE);		    nv = did_map ? NOTIFY_DONE : NOTIFY_IGNORED;		}    }      /* the following switch probably belongs in a state transition table */    switch (action) {	    case WIN_REPAINT:			ttysw_sigwinch(ttysw);			nv = NOTIFY_DONE;			break;		case WIN_RESIZE:			(void)ttysw_resize(ttysw);			nv = NOTIFY_DONE;			break;		case KBD_USE:			if ((Textsw)ttysw->ttysw_hist != textsw) {			    (Textsw)ttysw->ttysw_hist = textsw;			    (void)ttynewsize(textsw_screen_column_count(textsw),				textsw_screen_line_count(textsw));			    ttysw->ttysw_wfd =			    	(int)window_get((Window)(LINT_CAST(textsw)), WIN_FD);			}			break;		case KBD_DONE:			break;		case LOC_MOVE:			break;	    case LOC_STILL:			break;	    case LOC_WINENTER:		 	break;	    case LOC_WINEXIT:			break;	    default:#ifdef DEBUG	if (action <= ASCII_LAST) {	    int		ctrl_state = event->ie_shiftmask & CTRLMASK;	    int		shift_state = event->ie_shiftmask & SHIFTMASK;	    char	ie_code = action;	}#endif DEBUG			if (!cmdsw->cooked_echo)		   	    break;			/* Only send interrupts when characters are actually typed. */			if (action == cmdsw->tchars.t_intrc) {			    ttysw_sendsig(ttysw, textsw, SIGINT);			} else if (action == cmdsw->tchars.t_quitc) {			    ttysw_sendsig(ttysw, textsw, SIGQUIT);			} else if (action == cmdsw->ltchars.t_suspc			       ||  action == cmdsw->ltchars.t_dsuspc) {			    ttysw_sendsig(ttysw, textsw, SIGTSTP);			} else if (action == cmdsw->tchars.t_eofc) {			    if (insert == TEXTSW_INFINITY)				insert = (int)textsw_get(textsw, TEXTSW_INSERTION_POINT);			    if (length == TEXTSW_INFINITY)				length = (int)textsw_get(textsw, TEXTSW_LENGTH);			    if (length == insert) {				/* handle like newline or carriage return */				if (cmdsw->cmd_started				&&  length > textsw_find_mark(textsw, cmdsw->user_mark)) {				    if (ttysw_scan_for_completed_commands(ttysw, -1, 0))						nv = NOTIFY_IGNORED;					} else {					    /* but remember to send eot. */					    cmdsw->pty_eot = iwbp - ibuf;					    cmdsw->cmd_started = 0;					    (void)ttysw_reset_conditions(ttysw);					}			    } else {   /* length != insert */					nv = notify_next_event_func(						(Notify_client)(LINT_CAST(textsw)), 						(Notify_client)(LINT_CAST(event)), arg, type);			    }			}    }   /* switch */    return(nv);}static Notify_valuettysw_cr(ttysw, tty)    Ttysw                *ttysw;    int                   tty;{    int			  nfds = 0;    fd_set		  wfds;    static struct timeval timeout = {0, 0};    int maxfds	= GETDTABLESIZE();        /*     *  GROSS HACK:     *     *  There is a race condition such that between the notifier's     *  select() call and our write, the app may write to the tty,     *  causing our write to block.  The tty cannot be flushed because     *  we don't get to read the pty because our write is blocked.     *  This GROSS HACK doesn't eliminate the race condition; it merely     *  narrows the window, making it less likely to occur.     *  We don't do an fcntl(tty, FN_NODELAY) because that affects the     *  file, not merely the file descriptor, and we don't want to change     *  what the application thinks it sees.     *     *  The right solution is either to invent an ioctl that will allow     *  us to set the tty driver's notion of the cursor position, or to     *  avoid using the tty driver altogether.     */    FD_ZERO(&wfds);    FD_SET(tty, &wfds);    if ((nfds = select(maxfds, NULL, &wfds, NULL, &timeout)) < 0) {	perror("ttysw_cr: select");	return (NOTIFY_IGNORED);    }    /* if (nfds == 0 || !((1 << tty) & wfds)) { */    if (nfds == 0 || !FD_ISSET(tty, &wfds)) {	return (NOTIFY_IGNORED);    }    if (write(tty, "\r", 1) < 0) {	fprintf(stderr, "for ttysw %x, tty fd %d, ",		ttysw, ttysw->ttysw_tty);	perror("TTYSW tty write failure");

⌨️ 快捷键说明

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