📄 fv.tree.c
字号:
{ *s_p = NULL; s_p = second; width = Fv_fontwidth[*n_p-' ']; } *s_p++ = *n_p++; } *s_p = NULL; pw_text(Fv_tree.pw, x, f_p->y+(TREE_GLYPH_HEIGHT>>1), PIX_SRC | PIX_DST, Fv_font, first); if (!shadow) pw_text(Fv_tree.pw, x, f_p->y+TREE_GLYPH_HEIGHT-(TREE_GLYPH_HEIGHT>>2), PIX_SRC | PIX_DST, Fv_font, second);}staticcalc_tree(f_p, y) /* Calculate tree's coordinates */ register FV_TNODE *f_p; /* Current node */ int y; /* Current y level */{ register FV_TNODE *nf_p = NULL; /* Previous sibling */ register int stack = 0; /* Current stack level */ for (; f_p; f_p = f_p->sibling) { if (f_p->child && !(f_p->status & PRUNE)) { calc_tree(f_p->child,y+(TREE_GLYPH_HEIGHT<<1)); nf_p = f_p->child; for (; nf_p->sibling; nf_p = nf_p->sibling) ; f_p->x = f_p->child->x+((nf_p->x-f_p->child->x)/2); stack = 0; } else { if (stack>MAXSTACKDEPTH) { nf_p = NULL; Xpos -= GLYPH_WIDTH; } if (nf_p && (nf_p->child == NULL|| nf_p->status == PRUNE)) { Xpos += GLYPH_WIDTH>>2; ++stack; } else { stack = 0; Xpos += GLYPH_WIDTH+(GLYPH_WIDTH>>2); } f_p->x = Xpos; } if (Xpos>Xmax) Xmax = Xpos; f_p->stack = stack; f_p->y = y+(f_p->stack*((TREE_GLYPH_HEIGHT>>1)+ (TREE_GLYPH_HEIGHT>>3))); if (f_p->y > Ymax) Ymax = f_p->y; nf_p = f_p; }}staticdisplay_tree(f_p) /* Display tree at folder */ register FV_TNODE *f_p;{ register int x; for (; f_p; f_p = f_p->sibling) { pw_rop(Fv_tree.pw, f_p->x, f_p->y, GLYPH_WIDTH, TREE_GLYPH_HEIGHT, PIX_SRC, f_p==Fv_current?Fv_icon[FV_IOPENFOLDER]: f_p->mtime && !(f_p->status&PRUNE)? Fv_icon[FV_IFOLDER] : Fv_icon[FV_IUNEXPLFOLDER], 0, TREE_GLYPH_TOP); fv_put_text_on_folder(f_p); /* Connect node with parent */ if (f_p != Fv_thead && f_p->stack == 0) { /* Straight up to tab height... */ x = f_p->x+(GLYPH_WIDTH>>1); pw_vector(Fv_tree.pw, x, f_p->y+(TREE_GLYPH_HEIGHT>>3), x, f_p->y, PIX_SRC, 1); /* ...then arc to parent */ pw_vector(Fv_tree.pw, x, f_p->y, f_p->parent->x+(GLYPH_WIDTH>>1), f_p->y-TREE_GLYPH_HEIGHT, PIX_SRC, 1); } if (f_p->child && !(f_p->status & PRUNE)) display_tree(f_p->child); }}fv_drawtree(calc) /* Draw path pane */ BOOLEAN calc; /* Recalculate tree positions */{ FV_TNODE *saved_sibling; /* Lock and clear canvas... */#ifdef SV1 pw_lock(Fv_tree.pw, &Fv_tree.r);#endif /* Clear background */ pw_writebackground(Fv_tree.pw, Fv_tree.r.r_left, Fv_tree.r.r_top, Fv_tree.r.r_width, Fv_tree.r.r_height, PIX_CLR); if (Fv_treeview) { if (calc) { Xpos = MARGIN - (GLYPH_WIDTH+ (GLYPH_WIDTH>>2)); Xmax = Xpos; Ymax = MARGIN; calc_tree(Fv_thead, Ymax); Fv_dont_paint = TRUE; window_set(Fv_tree.canvas, CANVAS_WIDTH, Xmax+(GLYPH_WIDTH<<1), CANVAS_HEIGHT, Ymax+GLYPH_HEIGHT, 0); Fv_dont_paint = FALSE; } /* If we've changed the tree's root, we don't want to * display any of it's possible siblings... */ saved_sibling = Fv_thead->sibling; Fv_thead->sibling = NULL; display_tree(Fv_thead); Fv_thead->sibling = saved_sibling; reverse(Fv_tselected); } else draw_path();#ifdef SV1 pw_unlock(Fv_tree.pw); /* Unlock canvas */#endif}fv_showopen() /* Avoid repainting tree to show open folder */{ if (!Fv_treeview) { draw_path(); Fv_lastcurrent = Fv_current; return; } /* We've seen this folder already. Just * exchange the open folder icons... */ if (Fv_lastcurrent) { register FV_TNODE *f_p; pw_rop(Fv_tree.pw, Fv_lastcurrent->x, Fv_lastcurrent->y, GLYPH_WIDTH, TREE_GLYPH_HEIGHT, PIX_SRC, Fv_icon[FV_IFOLDER], 0, TREE_GLYPH_TOP); fv_put_text_on_folder(Fv_lastcurrent); f_p = Fv_lastcurrent->sibling; if (!Fv_lastcurrent->child && f_p && f_p->stack) { /* Open folder was in stack--repaint rest of * stack... */ for (; f_p && f_p->stack; f_p = f_p->sibling) { pw_rop(Fv_tree.pw, f_p->x, f_p->y, GLYPH_WIDTH, TREE_GLYPH_HEIGHT, PIX_SRC, f_p->mtime ? Fv_icon[FV_IFOLDER] : Fv_icon[FV_IUNEXPLFOLDER], 0, TREE_GLYPH_TOP); fv_put_text_on_folder(f_p); } } } pw_rop(Fv_tree.pw, Fv_current->x, Fv_current->y, GLYPH_WIDTH, TREE_GLYPH_HEIGHT, PIX_SRC, Fv_icon[FV_IOPENFOLDER], 0, TREE_GLYPH_TOP); fv_put_text_on_folder(Fv_current); /* Ensure that this folder is visible... */ fv_visiblefolder(Fv_current); Fv_lastcurrent = Fv_current;}staticdraw_path() /* Draw folder path */{ FV_TNODE *level[32]; /* Nodes in path */ register int x; /* X coordinate */ register int y; /* Y coordinate */ register int levelno; /* level array index */ register FV_TNODE *f_p; /* Node pointer */ /* Get full path name; back up tree */ f_p = Fv_current; for ( levelno = 0; f_p; f_p = f_p->parent, levelno++ ) { if ( levelno > 32 ) { fv_putmsg(TRUE, "> 32 levels deep", 0, 0); return; } level[levelno] = f_p; } y = Fv_tree.r.r_top + MARGIN; /* Do we have enough room to display full path? If not then * display from current folder back with a line to indicate * the truncation. */ if ((levelno*GLYPH_WIDTH) +((levelno)*(GLYPH_WIDTH>>2)) > Fv_tree.r.r_width) { levelno = (Fv_tree.r.r_width-MARGIN)/(GLYPH_WIDTH+ (GLYPH_WIDTH>>2)); if (levelno<1) levelno = 1; /* MUST be one visible! */ pw_vector(Fv_tree.pw, 0, y+(TREE_GLYPH_HEIGHT>>1), GLYPH_WIDTH>>2, y+(TREE_GLYPH_HEIGHT>>1), PIX_SRC, 1); } x = (GLYPH_WIDTH>>2)+Fv_tree.r.r_left; /* Display path */ Npath = levelno; levelno--; while (levelno > -1) { f_p = level[levelno]; pw_rop(Fv_tree.pw, x, y, GLYPH_WIDTH, TREE_GLYPH_HEIGHT, PIX_SRC, levelno ? Fv_icon[FV_IFOLDER] : Fv_icon[FV_IOPENFOLDER], 0, TREE_GLYPH_TOP); f_p->x = x; f_p->y = y; fv_put_text_on_folder(f_p); x += GLYPH_WIDTH + (GLYPH_WIDTH>>2); /* Connecting arc to next folder */ if (levelno) pw_vector(Fv_tree.pw, x-(GLYPH_WIDTH>>2), y+(TREE_GLYPH_HEIGHT>>1), x, y+(TREE_GLYPH_HEIGHT>>1), PIX_SRC, 1); levelno--; } Fv_lastcurrent = Fv_current; reverse(Fv_tselected);}static FV_TNODE *path_chosen(x, y) /* What path was chosen? */ register int x, y;{ register int w, fno; FV_TNODE *f_p; /* Check reasonable boundaries */ w = GLYPH_WIDTH+(GLYPH_WIDTH>>2); if (x<MARGIN || y<MARGIN || y>(MARGIN+TREE_GLYPH_HEIGHT) || x>(w*Npath)) return(NULL); /* Get folder number chosen (ensure that we're not in folder gap) */ x -= GLYPH_WIDTH>>2; fno = x / w; if (fno>0) x -= w*fno; if (x>GLYPH_WIDTH) return(NULL); fno++; f_p = Fv_current; while (fno < Npath) { f_p = f_p->parent; fno++; } return(f_p);}fv_visiblefolder(f_p) /* Make folder visible in tree */ register FV_TNODE *f_p;{ int newpos; /* Try and centre folder in window */ if (f_p->x < Fv_tree.r.r_left || f_p->x+(GLYPH_WIDTH>>1) > Fv_tree.r.r_left+Fv_tree.r.r_width) { newpos = f_p->x - (Fv_tree.r.r_width>>1); if (newpos<0) newpos = 0;#ifndef SV1 newpos /= 10;#endif scrollbar_scroll_to(Fv_tree.hsbar, newpos); } if (f_p->y < Fv_tree.r.r_top || f_p->y+(TREE_GLYPH_HEIGHT>>1) > Fv_tree.r.r_top+Fv_tree.r.r_height) { newpos = f_p->y - (Fv_tree.r.r_height>>1); if (newpos<0) newpos = 0;#ifndef SV1 newpos /= 10;#endif scrollbar_scroll_to(Fv_tree.vsbar, newpos); }}voidfv_addparent_button() /* Add tree root's parent */{ /* Restore current head */ if (Fv_sibling && Fv_sibling->parent == Fv_thead->parent) Fv_thead->sibling = Fv_sibling; add_parent(Fv_thead->parent);}staticadd_parent(f_p) /* Add parent to folder */ FV_TNODE *f_p;{ Fv_thead = f_p; fv_drawtree(TRUE); if (Fv_tselected) fv_visiblefolder(Fv_tselected); /* Track selected */}fv_hide_node() /* Don't show selected folder's descendents */{ BOOLEAN new; if (Fv_tselected->mtime == 0) { fv_busy_cursor(TRUE); fv_expand_node(Fv_tselected, &new); fv_busy_cursor(FALSE); if (!new) return; } else if (Fv_tselected->status & PRUNE) Fv_tselected->status &= ~PRUNE; else Fv_tselected->status |= PRUNE; fv_drawtree(TRUE); fv_visiblefolder(Fv_tselected); /* Track selected */}fv_set_root() /* Set tree root to current folder */{ if (Fv_tselected != Fv_thead) { Fv_sibling = Fv_tselected->sibling; Fv_tselected->sibling = NULL; add_parent(Fv_tselected); Fv_lastcurrent = NULL; }}fv_openfile(name, pattern, folder) /* Open a file */ char *name; /* File name (incl path) */ char *pattern; /* Pattern it matched */ BOOLEAN folder; /* Goto folder? */{ register char *n_p; /* Name pointer */ char *fname; /* File name (excl path) */ register FV_TNODE *f_p, *parent;/* Tree pointers */ register int more; /* More of path name to come? */ BOOLEAN make_folder = FALSE; /* Did we make a folder? */ FV_TNODE *child; /* Temp folder child */ if (folder) fname = NULL; else { /* Remove last component of path */ n_p = name; while (*n_p) n_p++; while (*n_p != '/' && n_p != name) n_p--; /* It's a filename, match it */ if (n_p == name) { fname = n_p; goto match; } fname = n_p+1; *n_p = NULL; } more = TRUE; if (*name == '/') { /* Begin at root... */ name++; if (*name == NULL) { more = FALSE; f_p = Fv_troot; } else { f_p = Fv_troot->child; parent = Fv_troot; } /* Make sure root is visible */ Fv_dont_paint = TRUE; while (Fv_thead != Fv_troot) fv_addparent_button(); Fv_dont_paint = FALSE; } else { /* Begin at selected or current folder... */ f_p = Fv_tselected ? Fv_tselected : Fv_current; parent = f_p; f_p = f_p->child; f_p->status &= ~PRUNE; } while (more) { /* Get next folder name... */ while (*name == '/') /* Skip extra /'s */ *name++; n_p = name; while (*n_p && *n_p != '/') n_p++; if (more = (*n_p=='/')) *n_p = NULL; else if (n_p==name) /* / at end */ break; for (; f_p; f_p = f_p->sibling) if (strcmp(f_p->name, name)==0) break; if (f_p) /* Found folder? */ { if (more) { parent = f_p; f_p = f_p->child; if (f_p) f_p->status &= ~PRUNE; } else break; /* Last folder in path */ } else /* We have to make folder */ { make_folder = TRUE; if (((f_p=(FV_TNODE *)fv_malloc(sizeof(FV_TNODE)))==NULL) || ((f_p->name=fv_malloc((unsigned)strlen(name)+1))==NULL)) return; if (parent && parent->mtime == 0 && parent->child) { /* Assign parent some bogus time so it thinks * we've seen this folder, (revisiting folder * will expand it, but preserve existing * children) */ parent->mtime = 10; } (void)strcpy(f_p->name, name); f_p->parent = parent; f_p->sibling = parent->child; f_p->child = NULL; f_p->status = 0; f_p->mtime = 0; parent->child = f_p; parent = f_p; } if (more) { *n_p = '/'; name = n_p+1; } } /* We've arrived at the correct folder */ if (fname) *(fname-1) = '/'; /* Restore name */ if (f_p != (Fv_tselected ? Fv_tselected : Fv_current)) { /* File isn't in current directory... */ fv_getpath(f_p, (char *)0); if (chdir(Fv_path)==-1) return; (void)strcpy(Fv_openfolder_path, Fv_path); Fv_current = f_p; /* Did folder repaint discover new folders? */ child = f_p->child; fv_display_folder(FV_BUILD_FOLDER); if (child != f_p->child) make_folder = TRUE; if (Fv_thead != Fv_troot && !fv_descendant(f_p, Fv_thead)) { /* Folder not in current subtree; back to real root */ Fv_thead->sibling = Fv_sibling; Fv_thead = Fv_troot; make_folder = TRUE; } if (make_folder || !Fv_treeview) fv_drawtree(make_folder); else fv_showopen(); if (Fv_treeview) { fv_visiblefolder(Fv_current); reverse(Fv_current); Lastselected = Fv_tselected = Fv_lastcurrent = Fv_current; } else Lastselected = Fv_tselected = Fv_lastcurrent = NULL; } /* If we were passed a pattern, then try and edit it, otherwise * just match it. */ if (fname) {match: if (*fname == '.' && !Fv_see_dot) fv_putmsg(TRUE, Fv_message[MEHIDDEN], 0, 0); else if (pattern) fv_gotofile(fname, pattern); else fv_match_files(fname); } else scrollbar_scroll_to(Fv_foldr.vsbar, 0);}fv_treedeselect() /* Deselect folder */{ reverse(Fv_tselected ? Fv_tselected : Lastselected); Lastselected = NULL; Fv_tselected = NULL;}fv_descendant(c_p, f_p) /* Search folder tree for descendant of folder */ FV_TNODE *c_p; FV_TNODE *f_p;{ if (c_p == f_p) return(TRUE); Child = c_p; Found_child = FALSE; descendant(f_p); return(Found_child);}staticdescendant(f_p) register FV_TNODE *f_p;{ if (Found_child) return; for ( ; f_p; f_p = f_p->sibling) if (f_p == Child) { Found_child = TRUE; break; } else if (f_p->child) descendant(f_p->child);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -