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

📄 fv.tree.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
#ifndef lintstatic  char sccsid[] = "@(#)fv.tree.c 1.1 92/07/30 Copyr 1988 Sun Micro";#endif/*	Copyright (c) 1987, 1988, Sun Microsystems, Inc.  All Rights Reserved.	Sun considers its source code as an unpublished, proprietary	trade secret, and it is available only under strict license	provisions.  This copyright notice is placed here only to protect	Sun in the event the source is deemed a published work.  Dissassembly,	decompilation, or other means of reducing the object code to human	readable form is prohibited by the license agreement under which	this code is provided to the user or company in possession of this	copy.	RESTRICTED RIGHTS LEGEND: Use, duplication, or disclosure by the 	Government is subject to restrictions as set forth in subparagraph 	(c)(1)(ii) of the Rights in Technical Data and Computer Software 	clause at DFARS 52.227-7013 and in similar clauses in the FAR and 	NASA FAR Supplement. */#include <stdio.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/file.h>#ifdef OS3# include <sys/dir.h>#else# include <dirent.h>#endif#ifdef SV1#include <suntool/sunview.h>#include <suntool/panel.h>#include <suntool/canvas.h>#include <suntool/scrollbar.h>#else#include <view2/view2.h>#include <view2/panel.h>#include <view2/canvas.h>#include <view2/scrollbar.h>#endif#include "fv.port.h"#include "fv.h"#include "fv.extern.h"#define MAXSTACKDEPTH	5			/* How deep folders can layer */#define THRESHOLD	4static short Xpos;				/* Tree position global */static short Xmax, Ymax;			/* Width, height of canvas */static int Npath;				/* Number of path buttons */static int Lastevent;				/* Last event seen */static FV_TNODE *Chosen;			/* Chosen folder (mouse()) */static FV_TNODE *Lastselected;			/* Last node selected */static FV_TNODE *Mouse_stack[MAXSTACKDEPTH];	/* Selection in folder stack */static FV_TNODE *Child;				/* Descendant node */static BOOLEAN Found_child;			/* Did we find it? */static FV_TNODE *path_chosen();static FV_TNODE *mouse();fv_create_tree_canvas(){	static int tree_repaint();	static Notify_value tree_event();	Fv_tree.canvas = window_create(Fv_frame, CANVAS,		CANVAS_AUTO_CLEAR,	FALSE,		CANVAS_AUTO_SHRINK,	FALSE,		CANVAS_FAST_MONO,	TRUE,		CANVAS_RETAINED,	FALSE,		CANVAS_REPAINT_PROC,	tree_repaint,		WIN_CONSUME_PICK_EVENTS,			KEY_LEFT(K_PROPS), KEY_LEFT(K_UNDO), KEY_LEFT(K_PUT),			KEY_LEFT(K_GET), KEY_LEFT(K_FIND), KEY_LEFT(K_DELETE),			0,		0);#ifdef SV1	Fv_tree.pw = (PAINTWIN)canvas_pixwin(Fv_tree.canvas);#else	Fv_tree.pw = (PAINTWIN)vu_get(Fv_tree.canvas, CANVAS_NTH_PAINT_WINDOW, 0);#endif        Fv_tree.r.r_width = (int)window_get(Fv_tree.canvas, WIN_WIDTH);	Fv_tree.r.r_height = (int)window_get(Fv_tree.canvas, WIN_HEIGHT);		 #ifdef SV1	notify_interpose_event_func(Fv_tree.canvas, tree_event, NOTIFY_SAFE);#else	notify_interpose_event_func(Fv_tree.pw, tree_event, NOTIFY_SAFE);#endif}static Notify_valuetree_event(cnvs, evnt, arg, typ)	Canvas cnvs;	register Event *evnt;	Notify_arg arg;	Notify_event_type typ;{	static struct timeval last_click;	/* Last time clicked */	struct timeval click;			/* This time clicked */	BOOLEAN children;			/* More children found? */	int x, y, i;				/* Last coordinates */	if (event_is_down(evnt))	if (event_id(evnt) == MS_LEFT)	{		/* Clear any message */		fv_clrmsg();		/* Single click = selection		 * Double click = open folder		 */		if (Fv_treeview)#ifdef SV1			Fv_tselected = mouse(event_x(evnt)+Fv_tree.r.r_left,				event_y(evnt)+Fv_tree.r.r_top, Fv_thead);#else			Fv_tselected = mouse(event_x(evnt), event_y(evnt), Fv_thead);#endif		else 			Fv_tselected = path_chosen(event_x(evnt), event_y(evnt));		if (Fv_tselected)		{			/* Only one window can have selections */			fv_filedeselect();			click = evnt->ie_time;			if (Lastselected == Fv_tselected)			{				if (click.tv_sec-last_click.tv_sec<=1)				{					if (Fv_treeview)						fv_open_folder();					else					{						fv_busy_cursor(TRUE);						Fv_current = Fv_tselected;						fv_getpath(Fv_tselected, (char *)0);						chdir(Fv_path);						(void)strcpy(Fv_openfolder_path, Fv_path);						fv_drawtree(TRUE);						fv_display_folder(FV_BUILD_FOLDER);						fv_busy_cursor(FALSE);					}					return(notify_next_event_func(cnvs, evnt,						arg, typ));				}			}			else			{				if (Fv_treeview)				{					fv_check_children(Fv_tselected, &children);					if (children)						fv_drawtree(TRUE);					else					{						reverse(Lastselected);						reverse(Fv_tselected);					}				}				else				{					reverse(Lastselected);					reverse(Fv_tselected);				}			}			last_click = click;			Lastselected = Fv_tselected;#ifdef SV1			if (Fv_treeview)			{				/* Drag folder? */				x = event_x(evnt);				y = event_y(evnt);				while (window_read_event(cnvs, evnt) != -1 &&					event_id(evnt) != MS_LEFT)					if (((i = x-event_x(evnt))>THRESHOLD) ||					      i<-THRESHOLD ||					    ((i = y-event_y(evnt))>THRESHOLD) ||					      i<-THRESHOLD)					{						drag(cnvs, x, y);						break;					}			}#endif		}		else		{			/* Clicking on white space clears selection */			fv_treedeselect();			fv_filedeselect();		}	}	else		if (event_id(evnt) == MS_RIGHT)			fv_viewmenu(cnvs, evnt, TRUE);	fv_check_keys(evnt);	Lastevent = event_id(evnt);	return(notify_next_event_func(cnvs,evnt,arg,typ));}/*ARGSUSED*/static voidtree_repaint(canvas, pw, area)			/* Repaint tree canvas */	Canvas canvas;	PAINTWIN pw;	Rectlist *area;{	register Rect *rn;	static BOOLEAN lastview=TRUE;		/* Last view state */	Fv_tree.r.r_height = (int)window_get(canvas, WIN_HEIGHT);	Fv_tree.r.r_width = (int)window_get(canvas, WIN_WIDTH);	rn = &area->rl_bound;#ifdef SV1	if (Fv_treeview && Lastevent == SCROLL_REQUEST)	{		/* The tree is visible; handle scrolling or repainting */		if (Fv_tree.r.r_left != rn->r_left)		{			/* Horizontal scroll */			if (rn->r_width+SCROLLBAR_WIDTH >= Fv_tree.r.r_width)				Fv_tree.r.r_left = rn->r_left;			else				Fv_tree.r.r_left += Fv_tree.r.r_left < rn->r_left							? rn->r_width							: -rn->r_width;		}		else if (Fv_tree.r.r_top != rn->r_top)		{			/* Vertical scroll */			if (rn->r_height+SCROLLBAR_WIDTH >= Fv_tree.r.r_height)				Fv_tree.r.r_top = rn->r_top;			else				Fv_tree.r.r_top += Fv_tree.r.r_top < rn->r_top 							? rn->r_height							:-rn->r_height;		}	}#else	Fv_tree.r.r_top = (int)scrollbar_get(Fv_tree.vsbar, 		SCROLL_VIEW_START) * 10 ;	Fv_tree.r.r_left = (int)scrollbar_get(Fv_tree.hsbar, 		SCROLL_VIEW_START) * 10 ;#endif	if (Fv_dont_paint)		return;	/* Recalculate tree positions when the tree view changes.  Always keep	 * open folder visible when state changes from path to tree...	 */	fv_drawtree((BOOLEAN)(lastview!=Fv_treeview));	if (!lastview && Fv_treeview && Fv_current)		fv_visiblefolder(Fv_current);	lastview = Fv_treeview;}#ifdef SV1staticdrag(cnvs, x, y)	Canvas cnvs;	register int x,y;			/* Mouse coordinate */{	register int x1, y1;			/* Next mouse coordinate */	register int tx, ty;			/* Folder coordinate */	int xoffset, yoffset;			/* Offsets into canvas */	Event ev;				/* Next event */	FV_TNODE *t_p;				/* We're over this node */	FV_TNODE *tree_target = 0;		/* Current open node */	FV_TNODE *tree_lock = 0;		/* Current locked node */	register FV_TNODE *selected = Fv_tselected;	/* Store selected */	char path[MAXPATH];			/* Target path */	window_set(cnvs, WIN_GRAB_ALL_INPUT, TRUE, 0);	tx = selected->x;	ty = selected->y;	xoffset = (int)scrollbar_get(Fv_tree.hsbar, SCROLL_VIEW_START);	yoffset = (int)scrollbar_get(Fv_tree.vsbar, SCROLL_VIEW_START);	while (window_read_event(cnvs, &ev) != -1 && event_id(&ev) != MS_LEFT)	{		pw_rop(Fv_tree.pw, tx, ty, GLYPH_WIDTH, TREE_GLYPH_HEIGHT,			PIX_SRC^PIX_DST, Fv_icon[FV_IFOLDER], 0, TREE_GLYPH_TOP);		x1 = event_x(&ev);		y1 = event_y(&ev);		tx += x1-x;		ty += y1-y;		t_p = mouse(x1+xoffset, y1+yoffset, Fv_thead);		fv_tree_feedback(t_p, &tree_target, &tree_lock, selected, path);		pw_rop(Fv_tree.pw, tx, ty, GLYPH_WIDTH, TREE_GLYPH_HEIGHT,			PIX_SRC^PIX_DST, Fv_icon[FV_IFOLDER], 0, TREE_GLYPH_TOP);		x = x1;		y = y1;	}	window_set(cnvs, WIN_GRAB_ALL_INPUT, FALSE, 0);	/* Remove last */	pw_rop(Fv_tree.pw, tx, ty, GLYPH_WIDTH, TREE_GLYPH_HEIGHT,		PIX_SRC^PIX_DST, Fv_icon[FV_IFOLDER], 0, TREE_GLYPH_TOP);	/* Replace original */	pw_rop(Fv_tree.pw, selected->x, selected->y, GLYPH_WIDTH, TREE_GLYPH_HEIGHT,		PIX_SRC^PIX_DST, Fv_icon[FV_IFOLDER], 0, TREE_GLYPH_TOP);	if (tree_target || tree_lock)	{		/* Make the move */		if (tree_target)		{			if (fv_move_copy(path, FALSE) == SUCCESS)			{				/* Isolate source node from branch */				t_p = selected->parent->child;				if (t_p == selected)					selected->parent->child = selected->sibling;				else				{					while (t_p && t_p->sibling != selected)						t_p = t_p->sibling;					if (t_p)						t_p->sibling = selected->sibling;				}				/* Insert source into target branch */				selected->sibling = tree_target->child;				selected->parent = tree_target;				tree_target->child = selected;				tree_target->mtime = time(0);				fv_sort_children(tree_target);				fv_getpath(selected, (char *)0);				fv_drawtree(TRUE);				return;			}		}		else			tree_target = tree_lock;		pw_rop(Fv_tree.pw, tree_target->x, tree_target->y,			GLYPH_WIDTH, TREE_GLYPH_HEIGHT, PIX_SRC, 			Fv_icon[FV_IFOLDER], 0, TREE_GLYPH_TOP);		fv_put_text_on_folder(tree_target);	}}#endiffv_tree_feedback(t_p, tree_target, tree_lock, self, target_tree_path)	register FV_TNODE *t_p;			/* We're over this node */	register FV_TNODE **tree_target;	/* Current open node */	register FV_TNODE **tree_lock;		/* Current locked node */	FV_TNODE *self;				/* Dragged node */	char *target_tree_path;			/* Open path */{	if (t_p && t_p != self)	{		if (t_p != *tree_target)		{			if (*tree_target)			{				/* Close previous open folder */				pw_rop(Fv_tree.pw, (*tree_target)->x, (*tree_target)->y,					GLYPH_WIDTH, GLYPH_HEIGHT, PIX_SRC, 					Fv_icon[FV_IFOLDER], 0, TREE_GLYPH_TOP);				fv_put_text_on_folder(*tree_target);				*tree_target = NULL;			}			fv_getpath(t_p, target_tree_path);			if (access(target_tree_path, W_OK) == 0)			{				/* We can place objects here,				 * open and invert new folder.				 */				*tree_target = t_p;				pw_rop(Fv_tree.pw, (*tree_target)->x, (*tree_target)->y,					GLYPH_WIDTH, TREE_GLYPH_HEIGHT, PIX_SRC,					Fv_icon[FV_IOPENFOLDER], 0, TREE_GLYPH_TOP);				fv_put_text_on_folder(t_p);				pw_rop(Fv_tree.pw, (*tree_target)->x, (*tree_target)->y,					GLYPH_WIDTH, TREE_GLYPH_HEIGHT,					PIX_SRC^PIX_DST, 					Fv_invert[FV_IOPENFOLDER], 0, TREE_GLYPH_TOP);			}			else if (*tree_lock != t_p)			{				if (*tree_lock)				{					/* Close previous locked folder */					pw_rop(Fv_tree.pw,						(*tree_lock)->x, (*tree_lock)->y,						GLYPH_WIDTH, TREE_GLYPH_HEIGHT,						PIX_SRC, Fv_icon[FV_IFOLDER],						0, TREE_GLYPH_TOP);					fv_put_text_on_folder(*tree_lock);				}				/* We can't place objects in this folder.  Show				 * lock.				 */				*tree_target = NULL;				*tree_lock = t_p;				pw_rop(Fv_tree.pw, (*tree_lock)->x, (*tree_lock)->y,					GLYPH_WIDTH, TREE_GLYPH_HEIGHT,					PIX_SRC, Fv_lock, 0, TREE_GLYPH_TOP);			}		}	}	else if (*tree_target || *tree_lock)	{		/* Over empty space; close/unlock folder */		if (*tree_lock)			*tree_target = *tree_lock;		pw_rop(Fv_tree.pw, (*tree_target)->x, (*tree_target)->y,			GLYPH_WIDTH, TREE_GLYPH_HEIGHT, PIX_SRC, 			Fv_icon[FV_IFOLDER], 0, TREE_GLYPH_TOP);		fv_put_text_on_folder(*tree_target);		*tree_target = NULL;		*tree_lock = NULL;	}}fv_init_tree()		/* Initialize tree. Called before window main loop. */{	register FV_TNODE *f_p, *nf_p;		/* Node pointers */	register char *n_p, *s_p;		/* String pointers */	BOOLEAN new;				/* function parameter */	if ( !getwd(Fv_path) )	{		(void)fprintf(stderr, Fv_message[MECHDIR], ".", 			sys_errlist[errno]);		exit(1);	}	(void)strcpy(Fv_openfolder_path, Fv_path);	/* Build tree */	if ( ((f_p = (FV_TNODE *)fv_malloc(sizeof(FV_TNODE))) == NULL) ||	     ((f_p->name = fv_malloc(2)) == NULL ))		exit(1);	Fv_troot = Fv_thead = f_p;	(void)strcpy(f_p->name, "/");	f_p->parent = f_p->sibling = NULL;	f_p->mtime = 0;	f_p->status = 0;	n_p = &Fv_path[1];	while ( *n_p )	{		/* Go down chain collecting names. (I assumed longest name		 * to be 20 characters...)		 */		if ( ((nf_p = (FV_TNODE *)fv_malloc(sizeof(FV_TNODE))) == NULL) ||		     ((nf_p->name = fv_malloc(20)) == NULL ))			exit(1);		f_p->child = nf_p;		nf_p->parent = f_p;		nf_p->sibling = NULL;		nf_p->mtime = 0;		nf_p->status = 0;		s_p = nf_p->name;		while ( *n_p && *n_p != '/' )		{			if ( s_p - nf_p->name < MAXPATH )				*s_p++ = *n_p;			else			{				fprintf(stderr, "path too long\n");				exit(1);			}			n_p++;		}		*s_p = NULL;		if ( *n_p )			n_p++;	/* Skip next / (if any) */		f_p = nf_p;	}	f_p->child = NULL;	Fv_current = f_p;	Fv_lastcurrent = f_p;	fv_add_children(f_p, &new, (char *)0);}fv_add_children(f_p, new, dname)		/* Add children to current node */	register FV_TNODE *f_p;			/* Node */	BOOLEAN *new;				/* Children found? */	char *dname;				/* Directory name */{	register FV_TNODE *nf_p;		/* Next tree pointer */	FV_TNODE *child[256];			/* Subdirectories */	register FV_TNODE *existing_child;	/* Ignore existing child */	register int nchild;			/* Number of children */	register struct dirent *dp;		/* File in directory */	DIR *dirp;				/* Directory file ptr */	struct stat fstatus;			/* Status info */	register int i;				/* Index */	static int compare_name();		/* Key compare */	BOOLEAN compare;	register char *c_p = 0;			/* String pointer */	/* If this directory is a symbolic link, note it and return */	if ((lstat(dname ? dname : Fv_path, &fstatus)==0) &&	    (fstatus.st_mode & S_IFMT) == S_IFLNK)	{		f_p->status |= SYMLINK;		*new = TRUE;		return(SUCCESS);	}	if (!dname)		dname = ".";	/* Bitch if we can't get in... */	if ( (stat(dname, &fstatus) == -1) ||	     ((dirp = opendir(dname)) == NULL) )	{		fv_putmsg(TRUE, sys_errlist[errno], 0, 0);		return(-1);	}	compare = f_p->mtime && f_p->child;	f_p->mtime = fstatus.st_mtime;	nchild = 0;	*new = FALSE;	while (dp=readdir(dirp))	{		/* Ignore '.' and '..' and any existing child.		 * (Names beginning with ".." are hidden for undelete)		 */		if (dp->d_name[0] == '.' && 		    (dp->d_name[1] == '.' || dp->d_name[1] == NULL))			continue;		if (!compare)			if ((f_p->child && 			    (strcmp(f_p->child->name,dp->d_name)==0)))				continue;		/* Not in the current folder?  Then affix path to name...*/		if (dname[0] != '.' && dname[1] != 0)		{			if (!c_p)			{				c_p = dname;			/* Get end of path */				while (*c_p)					c_p++;			}			*c_p = '/';			(void)strcpy(c_p+1, dp->d_name);	/* Copy in name */			i=stat(dname, &fstatus);			*c_p = NULL;			/* Null out name again*/		}		else			i=stat(dp->d_name, &fstatus);		if ( i == 0 && (fstatus.st_mode & S_IFMT) == S_IFDIR )		{			/* Found a directory, bitch and return if			 * we can't allocate memory for structure or			 * name.			 */			if (((nf_p = (FV_TNODE *)fv_malloc(sizeof(FV_TNODE))) == NULL)||			 ((nf_p->name = fv_malloc((unsigned)strlen(dp->d_name)+1))==NULL))				return(-1);			nf_p->parent = f_p;			nf_p->child = NULL;			(void)strcpy(nf_p->name, dp->d_name);			nf_p->mtime = 0;			nf_p->status = 0;			/* Remember each child */			child[nchild] = nf_p;			nchild++;			if (nchild==256)				break;		}	}	(void)closedir(dirp);	if (nchild)	{		if (nchild>1)		{			/* Sort children alphabetically */			qsort((char *)child, nchild, sizeof(FV_TNODE *),				compare_name);						/* Fix sibling pointers */			for (i = 1; i < nchild; i++)				child[i-1]->sibling = child[i];		}		child[nchild-1]->sibling = NULL;		if (compare)		{			compare_child(f_p->child, child[0], new);			return(SUCCESS);		}		existing_child = f_p->child;		f_p->child = child[0];		if (existing_child)		{

⌨️ 快捷键说明

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