|
|
Microsoft OS/2 SDK 03-01-1988
/* tree.c - build and maintain directory tree */
/* Created by Microsoft Corp. 1986 */
#include <malloc.h>
#include <memory.h>
#include <stdio.h>
#include "ds.h"
#include "vars.h"
/* Local variables */
static int ImageExists=FALSE; /* TRUE if image has been created */
/*** decorateTree - Decorate directory tree and build screen image
*
*
*/
decorateTree (root)
Directory *root;
{
LastRow = -1;
newLine ();
decorateSubTree (root, 0);
ImageExists = TRUE; /* Set flag for newLine() */
} /* decorateTree */
/*** decorateSubTree - Recursive portion called by decorateTree
*
*
*/
decorateSubTree (par, level)
Directory *par;
int level;
{
Directory *p;
int col,first;
first = TRUE;
col = level*D_INDENT;
p = par->d_child;
while (p) {
if (first) /* First subdir at this level */
first = FALSE; /* show on same row as parent */
else /* Not first at this level */
newLine(); /* Show underneath previous one */
p->d_row = LastRow;
p->d_col = col;
addImage (p,level); /* Add image for this directory */
decorateSubTree (p, level+1); /* Process subtree */
p = p->d_next;
} /* while */
} /* decorateSubTree */
/*** addImage - add image of one directory into screen image
*
*
*/
addImage (p,level)
Directory *p;
int level;
{
Directory *par;
int pLen,bLen,bCol;
char buf[MAX_COLS+1];
int parRow;
int row;
int col;
int distance;
cellType *c;
par = p->d_parent; /* Get parent pointer */
modLine (p->d_col, p->d_name, color[nameC]); /* Put directory name in image */
if (level > 0) { /* Draw line to parent */
distance = p->d_row - par->d_row;
if (distance == 0) { /* Parent on same row */
pLen = strlen (par->d_name);
bLen = D_INDENT - pLen; /* Length of bar */
bCol = par->d_col+pLen;
buf[bLen] = '\0'; /* Store string terminator */
memset (buf,LR_CHAR,bLen); /* Store bar in buffer */
modLine (bCol, buf, color[barC]); /* Put bar in image */
}
else { /* Parent is above */
bLen = D_INDENT;
bCol = par->d_col;
buf[bLen] = '\0'; /* Store string terminator */
memset (buf,LR_CHAR,bLen); /* Store bar in buffer */
buf[0] = RT_CHAR; /* Store angle char */
modLine (bCol, buf, color[barC]); /* Put bar in image */
row = LastRow-1;
col = par->d_col;
parRow = par->d_row;
while (row > parRow) { /* Finish path */
c = &DisplayRow[row][col];
switch (c->theChar) {
case ' ':
c->theChar = BT_CHAR;
c->theAttr = color[barC];
row--;
break;
case RT_CHAR:
c->theChar = BRT_CHAR;
row = 0;
break;
default:
row = 0;
break;
} /* switch */
} /* while */
} /* else (distance != 0) */
} /* if (level > 0) */
} /* addImage */
/*** newLine - add a new line to the scree image
*
*
*/
newLine ()
{
cellType *p;
int i;
if (++LastRow >= MAX_IMAGE_ROWS) { /* Too many image rows */
fprintf (stderr, "\nDirectory image too large - Internal error.\n");
exitError (2);
}
if (ImageExists) /* Get image row pointer */
p = DisplayRow[LastRow];
else /* Make new image row */
p = 0;
if (!p) { /* Have to make new image row */
p = (cellType *) calloc(N_of_Cols,sizeof(cellType));
if (!p) {
fprintf (stderr, "\nOut of memory - Allocating image line\n");
exitError (2);
}
DisplayRow[LastRow] = p; /* Store pointer to image row */
} /* if */
for (i=0; i<N_of_Cols; i++) { /* Blank out row */
p->theChar = ' ';
p->theAttr = color[blankC];
p++;
}
} /* newLine */
/*** modLine - store string with color in current line
*
*
*/
modLine (col, str, color)
int col;
NPCH str;
int color;
{
cellType *p;
char *s;
s = str;
p = &DisplayRow[LastRow][col];
while (*s) {
p->theChar = *s++;
p->theAttr = color;
p++;
} /* while */
} /* modLine */
Canonicalize (fullPath, p, headPath)
NPCH fullPath;
Directory *p;
NPCH headPath;
{
if (p->d_parent)
Canonicalize (fullPath, p->d_parent, headPath);
else
strcat (fullPath, headPath);
if (fullPath[strlen(fullPath)-1] != '\\')
strcat (fullPath, "\\");
strcat (fullPath, p->d_name);
}
/*** buildTree - scan directories breadth-first to build tree
*
*
*/
buildTree (par,parPath)
Directory *par;
NPCH parPath;
{
char sName[MAX_PATH_LEN]; /* Search path name */
Directory *child;
int errCode;
int sLen;
Attr a;
Cell c;
Directory *bfsHead;
Directory *bfsTail;
FileSearch sBuf; /* Find First/Next buffer */
unsigned sCount; /* Number of entries to search for */
HDIR sHandle; /* Search Handle */
bfsHead = par;
bfsTail = par;
c.ch = ' ';
c.at = color[blankC];
a = color[statusC];
while (bfsHead) {
sName[0] = '\0';
Canonicalize (sName, bfsHead, parPath);
sLen = strlen(sName);
VioWrtCharStrAtt (chfs(sName), sLen, WINDOW_TOP,0, afs(&a), VioHandle);
VioWrtNCell (cefs(&c), N_of_Cols-sLen, WINDOW_TOP,sLen, VioHandle);
if (sName[sLen-1] == '\\')
strcat (sName, "*.*");
else
strcat (sName, "\\*.*");
sHandle = -1; /* Family API only has one handle */
sCount = 1; /* Search for one at a time */
errCode = DosFindFirst (chfs(sName),
&sHandle,
DosAttrSubDir,
&sBuf,
sizeof(sBuf),
ufs(&sCount),
0L);
while (!errCode) {
if (sBuf.achName[0] != '.') { /* Not a back link */
if (sBuf.attrFile & DosAttrSubDir) { /* A subdirectory */
newDir (&child, sBuf.achName, bfsHead);
insDir (bfsHead, child, &bfsTail);
bfsTail->d_link = child;
bfsTail = child;
}
}
errCode = DosFindNext (sHandle,
&sBuf,
sizeof(sBuf),
ufs(&sCount));
}
DosFindClose (sHandle);
bfsHead = bfsHead->d_link;
}
} /* buildTree */
/*** insDir - insert child directory into tree in alphabetical order
*
*
*/
insDir (par,child)
Directory *par;
Directory *child;
{
Directory *p,*q;
p = par->d_child; /* p = first child */
q = 0; /* q = previous pointer */
while (p && (strcmp(child->d_name,p->d_name) > 0)) {
q = p; /* q = previous node */
p = p->d_next; /* p = next node */
}
if (!q) /* Insert at front of list */
par->d_child = child;
else /* Insert at middle or end of list */
q->d_next = child;
child->d_prev = q;
child->d_next = p;
if (p) /* Not inserting at end of list */
p->d_prev = child;
} /* insDir */
/*** newDir - create a new directory entry for tree
*
*
*/
newDir (dir,name,par)
Directory **dir;
NPCH name;
Directory *par;
{
Directory *p;
p = (Directory *) malloc (sizeof(Directory));
if (!p) {
fprintf (stderr, "\nOut of memory - Allocating directory node\n");
exitError (2);
}
p->d_name[0] = '\0';
strcpy (p->d_name,name);
p->d_parent = par;
p->d_prev = 0;
p->d_next = 0;
p->d_child = 0;
p->d_link = 0;
*dir = p; /* Return address of new dir node */
} /* newDir */
/*** pruneTree - prune subtree that has been deleted
*
* Called when we discover that a directory no longer exists.
*
* ENTRY: root = address of pointer to directory node that has evaporated.
*
* EXIT: root = address of pointer to some other node that is "close"
* to the evaporated node. Choose previous, next, or
* parent, in that order.
*/
pruneTree (curDir)
Directory **curDir;
{
Directory *p; /* Used to traverse tree */
Directory *q; /* Used to traverse tree */
Directory *n; /* Node to return */
p = *curDir; /* p = node to delete */
if (n = p->d_prev) { /* n = previous sibling */
q = p->d_next; /* q = next for n */
n->d_next = q; /* Point new node to new next */
if (q) /* Not last sibling */
q->d_prev = n; /* Point next back to new node */
}
else /* No previous sibling */
if (n = p->d_next) { /* n = next sibling */
n->d_prev = 0; /* Next sibling is now first */
q = n->d_parent; /* q = parent */
q->d_child = n; /* Point parent to new first child */
}
else
if (n = p->d_parent) /* n = parent */
if (n->d_parent) /* n is not root */
n->d_child = 0; /* Deleted only child of parent */
else {
fprintf (stderr, "directory tree is empty\n");
exit (2);
}
else {
fprintf (stderr, "directory tree is empty\n");
exit (2);
};
delDir (p); /* Delete subtree */
decorateTree (root); /* Re-build tree image */
stateModified = TRUE; /* Tree is modified */
*curDir = n; /* Return new node */
} /* pruneTree */
/*** delDir - Delete directory subtree
*
*
*/
delDir (root)
Directory *root;
{
Directory *p;
Directory *q;
p = root->d_child; /* p = first child */
while (p) { /* Still children to delete */
q = p;
p = p->d_next;
delDir (q);
}
free ( (char *) root);
} /* delDir */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.