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

📄 ovdir.c

📁 汇编语言编的关于ov143b.asm的小程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  036  8-Jun-87  ovdir.c

        Copyright (c) 1987 by Blue Sky Software.  All rights reserved.
*/

#include <stdio.h>
#include "ov.h"
#include "overr.h"
#include "menu.h"
#include "direct.h"
#include "strmem.h"
#include "dosfile.h"

#define DCOLSIZ 15
#define DCOLS (SCREEN_COLS / DCOLSIZ)

#define dr2sr(r) (FIRST_NROW + (r - drbase))
#define dc2sc(c) ((c - dcbase) * DCOLSIZ)

#define TO_NONE 0
#define TO_SUBDIR 1
#define TO_SIBLING 2
#define TO_PARENT 3
#define TO_ROOT 4

char *strrchr(), *strupr();
struct search_block *nxtfile();

struct dir_ent {
   struct dir_ent *subdir;
   struct dir_ent *sibling;
   struct dir_ent *parent;
   struct dir_ent *prev_sib;
   char name[13];
   unsigned char row;
   unsigned char col;
};

static last_drive = ' ';
static char dirpath[MAX_PATHLEN+6];
static int drbase, drend, dcbase, dcend;
static struct dir_ent *curdir, *logdir, *findir(), *dir_next();
static struct dir_ent root = { NULL, NULL, NULL, NULL, "", 0, 0 };

int dir_exit(), dir_login(), dir_mkdir(), dir_rmdir(), dir_new();
extern MENU top_file_menu[], *top_menu;

MENU top_dir_menu[] = {
   { "Login", "Login (switch) to the highlighted directory", dir_login, NULL },
   { "Mkdir", "Make a subdirectory of the highlighted directory", dir_mkdir, NULL },
   { "New", "Reread and redisplay directory tree", dir_new, NULL },
   { "Rmdir", "Remove (delete) the highlighted directory", dir_rmdir, NULL },
   { "Quit", "Return to file display", dir_exit, top_file_menu },
   { NULL, NULL, NULL, NULL }
};

extern WINDOW cw;
extern unsigned char dir_display, restricted;
char *strchr();


/******************************************************************************
 **                            D T R E E                                     **
 *****************************************************************************/

dtree() {              /* display / work with directory tree */

   int drive;

   dir_display = TRUE;                 /* dir tree is (will be) displayed */
   restricted = TRUE;                  /* disable some file commands */

   /* scan the current disk and create the internal directory tree if it
      hasn't already been built or the user has changed disks */

   if ((drive = current_drive()) != last_drive) {  /* has the drive switched? */

      if (root.subdir) {                       /* delete current tree */
         del_dtree(root.subdir);               /* if drive switch */
         root.subdir = NULL;
      }

      last_drive = drive;

      *dirpath = '\0';                         /* scan_dir() starts at */
      strncat(dirpath,cw.dirbuf,3);            /*   drives root dir */
      strcpy(root.name,dirpath);

      disp_msg(1,"Scanning disk");             /* takes awhile, tell user */

      scan_dir(&root);                         /* build new dir tree */
      dir_mark();                              /* assign row/col's to ent's */

      clr_msg();                               /* done scanning */

      drbase = dcbase = 0;                     /* assume dir */
      drend = NAME_ROWS;                         /* will start */
      dcend = DCOLS;                               /* at the root */
   }

   curdir = findir();                  /* locate current dir in tree */

   logdir = curdir;                    /* remember the logged dir */

   /* now display the current portion of the dir tree */

   adj_dir_dis();                      /* make sure logged dir will show */
   dir_distree();                      /* let user see it */

   top_menu = top_dir_menu;    /* setup the dir menu as the main menu */
}


/******************************************************************************
                              D I R _ N E W
 *****************************************************************************/

dir_new() {            /* rescan the disk and redisplay the dir tree */

   last_drive = ' ';   /* simply force a rescan */
   dtree();            /*   and let dtree() do the work */
   update_vol_stats(); /* in case its a new volume */
}


/******************************************************************************
 **                       D I R _ E X I T                                    **
 *****************************************************************************/

dir_exit() {           /* exit the dir display, return to file display */

   dir_display = FALSE;                /* dir tree will not be displayed */
   restricted = FALSE;                 /* allow all file commands */

   top_menu = top_file_menu;           /* file menu is main again */

   update_header();                    /* always rewrite the entire screen */
   refresh_screen(0);                  /* 'cause there may be > windows */
}


/******************************************************************************
 **                         S C A N _ D I R                                  **
 *****************************************************************************/

scan_dir(dp)           /* scan the specified dir tree for other directories */
struct dir_ent *dp;
{
   int dplen;
   int firsttime = TRUE;
   struct search_block *sbp;
   register struct dir_ent *ndp, *ldp = NULL;

   /* build the pathname of the dir to scan */

   dplen = strlen(dirpath);                    /* remember callers length */
   if (strcmp(dp->name+2,"\\") != 0) {         /* special case if root dir */
      strcat(dirpath,dp->name);                /* add name of dir to scan */
      strcat(dirpath,"\\");
   }
   strcat(dirpath,"*.*");                      /* add wildcard string */

   /* scan all files in directory looking for subdirectories.  When a
      subdirectory is found, add it to the dir_ent tree.  Note, the . and
      .. directory entries are ignored. */

   while (sbp = nxtfile(dirpath,0x16,&firsttime))
      if (sbp->attrib & DIR && *sbp->fn != '.') {

         /* found a subdir we want, build a struct dir_ent for it */
         ndp = (struct dir_ent *) Malloc(sizeof(struct dir_ent));
         strcpy(ndp->name,sbp->fn);
         ndp->subdir = NULL;
         ndp->sibling = NULL;
         ndp->parent = dp;
         ndp->prev_sib = ldp;

         /* now link it to the dir_ent tree either as a subdir of the
            parent (1st one only) or a sibling of the last one */

         if (ldp)
            ldp->sibling = ndp;        /* not 1st, is a sibling */
         else
            dp->subdir = ndp;          /* 1st one, subdir of parent */

         ldp = ndp;                    /* new one is now the last one */
      }

   /* if any subdirectories were found, scan 'em.  This isn't done
      earlier so the file search isn't complicated by the directory
      switches. */

   if (ldp) {                            /* NULL if no sub's found */
      dirpath[strlen(dirpath)-3] = '\0'; /* remove *.* for next level */
      ldp = dp->subdir;                  /* start with the first one */
      do {
         scan_dir(ldp);                /* call ourselves to scan this subtree */
      } while (ldp = ldp->sibling);    /* do all the subs found */
   }

   dirpath[dplen] = '\0';              /* restore dir pathname for caller */
}


/******************************************************************************
 **                           D E L _ D T R E E                              **
 *****************************************************************************/

del_dtree(dp)          /* purge the current in memory dir tree structure */
register struct dir_ent *dp;
{

   register struct dir_ent *ndp;

   /* delete this subdirectory ENTRY and all sibling ENTRIES (not the
      actual directories) */

   do {

      if (dp->subdir)            /* if it has a subdir, make a recursive call */
         del_dtree(dp->subdir);  /* to delete the substructure */

      ndp = dp->sibling;         /* get address of any sibling */

      free((char *)dp);          /* free the dir_ent space itself */

   } while (dp = ndp);           /* do until no more siblings */

}


/******************************************************************************
                           D I R _ D I S T R E E
 *****************************************************************************/

static int
dir_distree() {        /* display the dir tree */

   register int drow;
   int i, ldrow = -1;
   register struct dir_ent *dp = &root;

   do {

      drow = dp->row;          /* speed things up a little */

      /* if drow != ldrow, then this is the first entry on this display
         row, clear the line to remove any old junk that might be there */

      if (drow != ldrow && drow >= drbase && drow < drend) {
         gotorc(dr2sr(drow),dc2sc(dcbase));
         clr_eol();
         ldrow = drow;
      }

      /* see if its necessary to put some spacer bars in from the previous
         sibling.  This will be necessary if the prev_sib had a desendent
         with siblings because the siblings will occupy display lines
         between this ent's prev_sib and where this ent goes. */

      if (dp->prev_sib && (i = drow - dp->prev_sib->row - 1) > 0)
         for (; i; i--)
            if (dir_on_screen(drow-i,dp->col))
               disp_char_at(0xb3,dr2sr(drow-i),dc2sc(dp->col));

      /* only display a dir entry if it falls within the boundries, figure
         out if this one does and display the name if so - the dir under
         the pointer is highlighted, the logged dir is 'tagged' all others
         are displayed 'normal' */

      if (dir_on_screen(drow,dp->col))
         disp_dir_name(dp,dp == curdir ? DIS_HIGH :
                       (dp == logdir ? DIS_TAGD : DIS_NORM));

   } while (dp = dir_next(dp,&i,&i));

   /* if we didn't reach the bottom of the display area, clear out the rest
      of the lines to remove any garbage that might be there */

   drow++;                             /* next would be display row */
   if (drow - drbase < NAME_ROWS)
      for (; drow - drbase < NAME_ROWS; drow++) {
         gotorc(dr2sr(drow),dc2sc(dcbase));
         clr_eol();
      }
}


/******************************************************************************
 **                    D I S P _ D I R _ N A M E                             **
 *****************************************************************************/

disp_dir_name(dp,va)   /* display a single dir name */
register struct dir_ent *dp;
int va;
{
   gotorc(dr2sr(dp->row),dc2sc(dp->col));      /* move to display location */

   /* display the leadin bar to the dir name, it depends on whether
      this is the root, the 1st subdir, the last sibling, and if any
      siblings follow */

   if (dp->col) {                                 /* root dir? */
      if (dp->prev_sib == NULL)                   /* 1st subdir? */
         disp_char((dp->sibling) ? 0xc2 : 0xc4);  /* siblings follow? */
      else
         disp_char((dp->sibling) ? 0xc3 : 0xc0);
   } else
      disp_char(' ');                          /* root - no leadin */

   if (va != DIS_NORM)                         /* setup highlight if needed */
      setvattrib(va);

   disp_char(' ');
   disp_str(dp->name);                         /* display the name */
   disp_char(' ');

   /* draw bar to subdir or blank fill name */

   disp_rep(dp->subdir ? 0xc4 : ' ',DCOLSIZ - strlen(dp->name) - 3);

   if (va != DIS_NORM)         /* restore normal attribute if changed */
      setvattrib(DIS_NORM);
}


/*****************************************************************************
                             D I R _ M A R K
 *****************************************************************************/

static int
dir_mark() {   /* mark dir_ent's with logical row/column where they display */

   register struct dir_ent *dp;
   int nxtype, backup, drow, dcol;

   dp = &root;
   drow = dcol = 0;

   /* scan the dir_ent tree in order */

   while (dp = dir_next(dp,&nxtype,&backup)) {
      if (nxtype) {                            /* NZ if dp is a sibling */
         drow++;                               /* siblings go down a row */
         dcol -= backup;                       /* and maybe back some */
      } else
         dcol++;                               /* sub dir's go over a column */
      dp->row = drow;                          /* assign row/col to entry */
      dp->col = dcol;
   }
}


/******************************************************************************
                               D I R _ N E X T
 ******************************************************************************/

static struct dir_ent *
dir_next(dp,tp,bp)     /* return address of next dir_ent */
register struct dir_ent *dp;
int *tp, *bp;
{
   *bp = 0;                    /* assume we will not backup to parent */

   if (dp->subdir) {           /* subdir is next if there is one */
      *tp = 0;                 /* tell caller its a sub dir */
      return(dp->subdir);
   }

   *tp = 1;                    /* assume a sibling will be found */

   if (dp->sibling)            /* a sibling is next if there is one */
      return(dp->sibling);

   /* keep backing up until a parent is found with a sibling or root */

⌨️ 快捷键说明

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