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

📄 reply.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
字号:
#ifndef lint#ifdef sccsstatic  char sccsid[] = "@(#)reply.c 1.1 92/07/30 Copyr 1987 Sun Micro";#endif#endif/* * Copyright (c) 1987 by Sun Microsystems, Inc. *//* * Mailtool - managing the message composition window */#include <stdio.h>#include <errno.h>#include <signal.h>#include <ctype.h>#include <sunwindow/window_hs.h>#include <sys/stat.h>#include <sys/types.h>#include <sundev/kbd.h>#include <suntool/window.h>#include <suntool/frame.h>#include <suntool/panel.h>#include <suntool/text.h>#include <suntool/walkmenu.h>#include <suntool/scrollbar.h>#include "glob.h"#include "tool.h"static	struct reply_panel_data		 *mt_create_new_replysw();static Notify_value 	mt_destroy_replysw_proc();static int 	mt_get_kbd_process();struct reply_panel_data *mt_get_replysw(item)	Panel_item      item;{	Panel           panel;	struct reply_panel_data *ptr, *last_ptr, *value;	/*	 * loop through all replysw's looking for one that is displayed and	 * not in use. If none exist, take first one that is not in use and	 * display it. If none exist, create a new one. 	 */	panel = NULL;	if (item) {		panel = panel_get(item, PANEL_PARENT_PANEL);		ptr = (struct reply_panel_data *)panel_get(			panel, PANEL_CLIENT_DATA);	}	if (panel && panel != mt_cmdpanel)		/*		 * if this button was not on the command panel, then take		 * this replysw without looking further. Don't do inuse		 * check. This allows user to use 'deliver, leave intact'		 * option and then wrap new To: Subject: header around it 		 */		return (ptr);	value = last_ptr = NULL;	ptr = (struct reply_panel_data *)panel_get(		mt_cmdpanel, PANEL_CLIENT_DATA);	while (ptr) {		if (!ptr->inuse && ptr->replysw &&			(!mt_always_use_popup || (ptr->frame != mt_frame))) {			/*			 * if mt_always_use_popup is TRUE and this is the			 * split window, don't use it. This allows user to			 * set mt_always_use_popup during a session and do a			 * source and have the right thing happen. It also			 * allows the OPEN AND COMPOSE menu item to cause a			 * popup to be used, even where the user has not set			 * the default to be "alwaysusepopup"			 */			char	current_filename[1024];			current_filename[0] = '\0';			(void)textsw_append_file_name(ptr->replysw,				current_filename);			if (current_filename[0] != '\0' ||				window_get(ptr->replysw, TEXTSW_MODIFIED)) 				/*				 * without clicking compose or reply, user				 * has loaded a file into composition window				 * or has entered text directly. Only occurs				 * in popup windows, since ptr->inuse is				 * always true for split composition window,				 * because only way to open the window is via				 * compose or reply button. 				 */				ptr->inuse = TRUE;			else if (window_get(ptr->replysw, WIN_SHOW) &&				window_get(ptr->frame, WIN_SHOW) &&				!window_get(ptr->frame, FRAME_CLOSED) )			    		return(ptr); /* visible, use this */			else if (value == NULL)			/*			 * this one not in use, but not displayed. remember			 * it but look further.  			 */				value = ptr;		}		last_ptr = ptr;		ptr = ptr->next_ptr;	}	if (!value) {		if (mt_3x_compatibility) {			mt_warn(mt_frame, "Already replying.", 0);			return(NULL);		}		value = mt_create_new_replysw();		if (last_ptr)			last_ptr->next_ptr = value;		else			(void) panel_set(mt_cmdpanel, PANEL_CLIENT_DATA, value, 0);				/*				 * occurs if default is alwaysusepopup, and				 * this is the first replysw to be created 				 */	}	return (value);}static struct reply_panel_data *mt_create_new_replysw(){	Frame           frame;	struct reply_panel_data *ptr;	int             height;	if (mt_debugging)  {		(void) printf("creating replysw, #fds = %d\n", nfds_avail());		fflush(stdout);	}	if (nfds_avail() < 8) { 		mt_warn(mt_frame, "Not enough fds for any more popup windows.",			0);		/*		 * Three fds are used in creating the popup, one for the frame,		 * and one each for the two subwindows. Two more fds will be		 * consumed in loading the replysw, for a total of 5. It		 * requires 3 fds in order to be able to do a deliver because		 * of the way that textsw does saves. Therefore, you must		 * have at least 8 fds at this point.  		 */		return(NULL);	}	frame = window_create(NULL, FRAME,		WIN_ERROR_MSG, "Unable to create reply frame\n",		WIN_SHOW, 	FALSE,		WIN_WIDTH, 	window_get(mt_frame, WIN_WIDTH),		WIN_ROWS, 	mt_popuplines + 3,			/* allow for height of reply panel */		FRAME_LABEL, 	"Reply to or Compose Mail",		FRAME_SHOW_LABEL, TRUE,		FRAME_ICON,	&mt_empty_letter_icon,		0);	if (frame == NULL) {		if (mt_debugging)			(void)fprintf(stderr,"Unable to create reply frame\n");		mt_warn(frame, "Unable to create reply frame", 0);		return (NULL);	}	height = (int)window_get(frame, WIN_HEIGHT);	(void) window_set(frame,		WIN_Y, screenrect.r_height - height,		WIN_X, (int)window_get(mt_frame, WIN_X),		0);		/*		 * position popup below tool, if possible, but make sure that		 * it stays completely in view 		 */	ptr = mt_create_reply_panel(frame);	if (ptr == NULL) 	/* unable to create reply panel */	{		/* warning message already given - so stifle this one		   mt_warn(frame, "Unable to create composition window.", 0);		*/		/* turn off destroy confirmation alert */		(void)window_set(frame, FRAME_NO_CONFIRM, TRUE, 0);		/*		 * Note: the interpose function mt_destroy_replysw_proc		 * is set later, so this will correctly free the frame memory		 * without first calling mt_destroy_replysw_proc.		 */		(void)window_destroy(frame);		return(NULL);	}		/* catch when being destroyed */	notify_interpose_destroy_func(frame, mt_destroy_replysw_proc);	mt_add_window(frame, mt_Frame);	(void) window_set(ptr->reply_panel, WIN_SHOW, TRUE, 0);	(void) window_set(ptr->replysw,		WIN_X, 0,		WIN_BELOW, ptr->reply_panel,		WIN_SHOW, TRUE,		0);	(void) window_set(frame, WIN_CLIENT_DATA, ptr, 0);	/*	 * so can get from frame to reply panel data 	 */	return (ptr);}/* * user is quitting a popup reply window. This takes care of removing the * window from the tools data structures  */static Notify_value mt_destroy_replysw_proc(client, status)	Notify_client   client;	Destroy_status  status;{	if (status == DESTROY_CHECKING) {		struct reply_panel_data *ptr;				ptr = (struct reply_panel_data *)window_get(				client, WIN_CLIENT_DATA);		if (!mt_destroying && !mt_confirm(client, FALSE,				!window_get(ptr->replysw, TEXTSW_MODIFIED),				/*				 * alert is optional if window has not been				 * changed				 */				"Confirm",				"Cancel",				"Are you sure you want to Quit composition window?",				0)) {			notify_veto_destroy(client);			return (NOTIFY_DONE);		} else {			struct reply_panel_data *ptr, *prev;			prev = NULL;			ptr = (struct reply_panel_data *)panel_get(				mt_cmdpanel, PANEL_CLIENT_DATA);			while (ptr) {				if (client == ptr->frame) {					/* found it.  splice it out of chain */					mt_remove_window(ptr->replysw);					mt_remove_window(ptr->reply_panel);					mt_remove_window(ptr->frame);					textsw_reset(ptr->replysw, 0, 0);					textsw_reset(ptr->replysw, 0, 0);					/*					 * to avoid veto by textsw if any					 * edits 					 */					if (prev)						prev->next_ptr = ptr->next_ptr;					else						(void) panel_set(mt_cmdpanel,							PANEL_CLIENT_DATA,							ptr->next_ptr, 0);					break;				}				prev = ptr;				ptr = ptr->next_ptr;			}			mt_update_info("");		}	} 	(void) window_set(client, FRAME_NO_CONFIRM, TRUE, 0);	return (notify_next_destroy_func(client, status));}voidmt_start_reply(ptr)	struct reply_panel_data *ptr;{	Frame           frame;	int             percent, height;	Textsw          next_split;	char           *p;	frame = ptr->frame;	mt_replypanel_init(ptr->reply_panel);	if (frame == mt_frame && !window_get(ptr->replysw, WIN_SHOW)) {		if ((p = mt_value("msgpercent")) != NULL) {			percent = atoi(p);			if (percent >= 100)				percent = 50;		} else			percent = 50;		height = 0;		/*		 * destroy all splits because too hard to figure out what		 * height to give them when create composition window, and		 * then restore them after message is delivered or cancelled 		 */		while (next_split = (Textsw)textsw_next(			(Textsw)textsw_first(mt_msgsw))) {			height = height + 5 +				(int)window_get(next_split, WIN_HEIGHT);			/* 5 for the border */			(void)notify_post_destroy(next_split, DESTROY_CLEANUP,				NOTIFY_IMMEDIATE);		/*		 * XXX shouldn't have to cast value. Problem is textsw_first		 * textsw_next not extern in Textsw.h SHould be fixed 		 */		}		height = (height + (int)window_get(mt_msgsw, WIN_HEIGHT) -			(mt_3x_compatibility				? 0				: (int)window_get(ptr->reply_panel,					WIN_HEIGHT))  )		  	* percent / 100;		(void) window_set(mt_msgsw, WIN_HEIGHT, height, 0);		if (mt_3x_compatibility) {			(void)panel_set(mt_deliver_item,				PANEL_SHOW_ITEM, TRUE, 0);			(void)panel_set(mt_cancel_item,				PANEL_SHOW_ITEM, TRUE, 0);			(void) window_set(ptr->replysw,				WIN_X, 0,				WIN_BELOW, mt_msgsw,				WIN_SHOW, TRUE,				WIN_HEIGHT, WIN_EXTEND_TO_EDGE,				0);		} else {			(void) window_set(ptr->reply_panel,				WIN_X, 0,				WIN_BELOW, mt_msgsw,				WIN_SHOW, TRUE,				0);			(void) window_set(ptr->replysw,				WIN_X, 0,				WIN_BELOW, ptr->reply_panel,				WIN_SHOW, TRUE,				WIN_HEIGHT, WIN_EXTEND_TO_EDGE,				0);		}	}	ptr->inuse = TRUE; 	ptr->normalized = FALSE;	/*	 * work around to defer normalization until repaint actually occurs.	 * Problem is that textsw_possibly_normalize uses information in line	 * tables, which are not updated until the repaint.  When	 * mt_replysw_event_proc gets a WIN_PAINT event, and ptr->normalized	 * is FALSE, it also does a textsw_possibly_normalize.	 */}voidmt_display_reply(ptr)	struct reply_panel_data *ptr;{	Frame           frame;	frame = ptr->frame;	if (!window_get(frame, WIN_SHOW)) 		(void) window_set(frame, WIN_SHOW, TRUE, 0);	else if (window_get(frame, FRAME_CLOSED))		(void) window_set(frame, FRAME_CLOSED, FALSE, 0); 	else if (frame != mt_frame) {		int	framefd = window_fd(frame);    		int	rootfd = rootfd_for_toolfd(framefd);		wmgr_top(framefd, rootfd);	/* move popup to top */		(void)close(rootfd);	}	mt_move_input_focus(ptr->replysw);		if (mt_retained)		textsw_insert_makes_visible(ptr->replysw);	/*	 * if the user is running with *retained* text windows, then a	 * WIN_PAINT event will never happen. However, in this case, it is	 * safe to do the textsw_insert_makes_visible at this point, because	 * the window would have already been repainted at this point. Thus	 * this textsw_insert_makes_visible handles normalizing the window when	 * it is retained, and the one in mt_replysw_event_proc handles	 * normalization when the window is not retained.	 */}voidmt_move_input_focus(replysw)	Textsw          replysw;{	int             focus;	if (mt_value("moveinputfocus")		|| (focus = mt_get_kbd_process()) < 0		|| focus == getpid())		(void) window_set(replysw, WIN_KBD_FOCUS, TRUE, 0);}/* * Done doing a reply (or send, or forward). * Close the reply subwindow destroying its * split views. */voidmt_stop_reply(ptr)	struct reply_panel_data *ptr;{	Textsw          next_split;	Frame           frame;	/* destroy any reply subwindow split views */	while (next_split = (Textsw)textsw_next(				(Textsw)textsw_first(ptr->replysw)))		(void)notify_post_destroy(next_split, DESTROY_CLEANUP,			NOTIFY_IMMEDIATE);        /*	 * (Bug# 1018269 fix) destroy any message subwindow split views 	 * the user may have conjured up while the reply subwindow	 * was up.	 */	while (next_split = (Textsw)textsw_next(    				(Textsw)textsw_first(mt_msgsw)))		(void)notify_post_destroy(next_split, DESTROY_CLEANUP,			NOTIFY_IMMEDIATE);	textsw_reset(ptr->replysw);	frame = ptr->frame;	if (mt_3x_compatibility) {		(void)panel_set(mt_deliver_item, PANEL_SHOW_ITEM, FALSE, 0);		(void)panel_set(mt_cancel_item, PANEL_SHOW_ITEM, FALSE, 0);	}	if (frame != mt_frame) 		(void) window_set(frame, WIN_SHOW, FALSE, 0);	else {		(void) window_set(ptr->reply_panel, WIN_SHOW, FALSE, 0);		(void) window_set(ptr->replysw, WIN_SHOW, FALSE, 0);		(void) window_set(mt_msgsw, WIN_HEIGHT, WIN_EXTEND_TO_EDGE, 0);	}}/* * Get the process id of the process holding the keyboard focus. */static intmt_get_kbd_process(){	int             fd, num;	char            name[WIN_NAMESIZE];	if ((fd = (int)window_get(mt_msgsw, WIN_FD, 0)) < 0)		return (fd);	if ((num = win_get_kbd_focus(fd)) == WIN_NULLLINK)		return (-1);	(void)win_numbertoname(num, name);	if ((fd = open(name)) < 0)		return (fd);	num = win_getowner(fd);	(void)close(fd);	return (num);}

⌨️ 快捷键说明

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