|
|
1.1.1.2 ! root 1: /* tree.c - build and maintain directory tree */ ! 2: /* Created by Microsoft Corp. 1986 */ ! 3: 1.1 root 4: 5: #include <malloc.h> 6: #include <memory.h> 7: #include <stdio.h> 8: 9: #include "ds.h" 10: #include "vars.h" 11: 12: /* Local variables */ 13: 14: static int ImageExists=FALSE; /* TRUE if image has been created */ 15: 16: 17: /*** decorateTree - Decorate directory tree and build screen image 18: * 19: * 20: */ 21: decorateTree (root) 22: Directory *root; 23: { 24: LastRow = -1; 25: newLine (); 26: decorateSubTree (root, 0); 27: ImageExists = TRUE; /* Set flag for newLine() */ 28: } /* decorateTree */ 29: 30: 31: /*** decorateSubTree - Recursive portion called by decorateTree 32: * 33: * 34: */ 35: decorateSubTree (par, level) 36: Directory *par; 37: int level; 38: { 39: Directory *p; 40: int col,first; 41: 42: first = TRUE; 43: col = level*D_INDENT; 44: p = par->d_child; 45: while (p) { 46: if (first) /* First subdir at this level */ 47: first = FALSE; /* show on same row as parent */ 48: else /* Not first at this level */ 49: newLine(); /* Show underneath previous one */ 50: p->d_row = LastRow; 51: p->d_col = col; 52: addImage (p,level); /* Add image for this directory */ 53: decorateSubTree (p, level+1); /* Process subtree */ 54: p = p->d_next; 55: } /* while */ 56: } /* decorateSubTree */ 57: 58: 59: /*** addImage - add image of one directory into screen image 60: * 61: * 62: */ 63: addImage (p,level) 64: Directory *p; 65: int level; 66: { 67: Directory *par; 68: int pLen,bLen,bCol; 69: char buf[MAX_COLS+1]; 70: int parRow; 71: int row; 72: int col; 73: int distance; 74: cellType *c; 75: 76: par = p->d_parent; /* Get parent pointer */ 77: modLine (p->d_col, p->d_name, color[nameC]); /* Put directory name in image */ 78: if (level > 0) { /* Draw line to parent */ 79: distance = p->d_row - par->d_row; 80: if (distance == 0) { /* Parent on same row */ 81: pLen = strlen (par->d_name); 82: bLen = D_INDENT - pLen; /* Length of bar */ 83: bCol = par->d_col+pLen; 84: buf[bLen] = '\0'; /* Store string terminator */ 85: memset (buf,LR_CHAR,bLen); /* Store bar in buffer */ 86: modLine (bCol, buf, color[barC]); /* Put bar in image */ 87: } 88: else { /* Parent is above */ 89: bLen = D_INDENT; 90: bCol = par->d_col; 91: buf[bLen] = '\0'; /* Store string terminator */ 92: memset (buf,LR_CHAR,bLen); /* Store bar in buffer */ 93: buf[0] = RT_CHAR; /* Store angle char */ 94: modLine (bCol, buf, color[barC]); /* Put bar in image */ 95: row = LastRow-1; 96: col = par->d_col; 97: parRow = par->d_row; 98: while (row > parRow) { /* Finish path */ 99: c = &DisplayRow[row][col]; 100: switch (c->theChar) { 101: case ' ': 102: c->theChar = BT_CHAR; 103: c->theAttr = color[barC]; 104: row--; 105: break; 106: 107: case RT_CHAR: 108: c->theChar = BRT_CHAR; 109: row = 0; 110: break; 111: 112: default: 113: row = 0; 114: break; 115: } /* switch */ 116: } /* while */ 117: } /* else (distance != 0) */ 118: } /* if (level > 0) */ 119: } /* addImage */ 120: 121: 122: /*** newLine - add a new line to the scree image 123: * 124: * 125: */ 126: newLine () 127: { 128: cellType *p; 129: int i; 130: 131: if (++LastRow >= MAX_IMAGE_ROWS) { /* Too many image rows */ 132: fprintf (stderr, "\nDirectory image too large - Internal error.\n"); 133: exitError (2); 134: } 135: if (ImageExists) /* Get image row pointer */ 136: p = DisplayRow[LastRow]; 137: else /* Make new image row */ 138: p = 0; 139: if (!p) { /* Have to make new image row */ 140: p = (cellType *) calloc(N_of_Cols,sizeof(cellType)); 141: if (!p) { 142: fprintf (stderr, "\nOut of memory - Allocating image line\n"); 143: exitError (2); 144: } 145: DisplayRow[LastRow] = p; /* Store pointer to image row */ 146: } /* if */ 147: for (i=0; i<N_of_Cols; i++) { /* Blank out row */ 148: p->theChar = ' '; 149: p->theAttr = color[blankC]; 150: p++; 151: } 152: } /* newLine */ 153: 154: 155: /*** modLine - store string with color in current line 156: * 157: * 158: */ 159: modLine (col, str, color) 160: int col; 1.1.1.2 ! root 161: NPCH str; 1.1 root 162: int color; 163: { 164: cellType *p; 165: char *s; 166: 167: s = str; 168: p = &DisplayRow[LastRow][col]; 169: while (*s) { 170: p->theChar = *s++; 171: p->theAttr = color; 172: p++; 173: } /* while */ 174: } /* modLine */ 175: 176: 177: Canonicalize (fullPath, p, headPath) 1.1.1.2 ! root 178: NPCH fullPath; 1.1 root 179: Directory *p; 1.1.1.2 ! root 180: NPCH headPath; 1.1 root 181: { 182: if (p->d_parent) 183: Canonicalize (fullPath, p->d_parent, headPath); 184: else 185: strcat (fullPath, headPath); 186: if (fullPath[strlen(fullPath)-1] != '\\') 187: strcat (fullPath, "\\"); 188: strcat (fullPath, p->d_name); 189: } 190: 191: 192: /*** buildTree - scan directories breadth-first to build tree 193: * 194: * 195: */ 196: buildTree (par,parPath) 197: Directory *par; 1.1.1.2 ! root 198: NPCH parPath; 1.1 root 199: { 200: char sName[MAX_PATH_LEN]; /* Search path name */ 201: Directory *child; 202: int errCode; 203: int sLen; 204: Attr a; 205: Cell c; 206: Directory *bfsHead; 207: Directory *bfsTail; 208: FileSearch sBuf; /* Find First/Next buffer */ 209: unsigned sCount; /* Number of entries to search for */ 1.1.1.2 ! root 210: HDIR sHandle; /* Search Handle */ 1.1 root 211: 212: bfsHead = par; 213: bfsTail = par; 214: c.ch = ' '; 215: c.at = color[blankC]; 216: a = color[statusC]; 217: 218: while (bfsHead) { 219: sName[0] = '\0'; 220: Canonicalize (sName, bfsHead, parPath); 221: 222: sLen = strlen(sName); 1.1.1.2 ! root 223: VioWrtCharStrAtt (chfs(sName), sLen, WINDOW_TOP,0, afs(&a), VioHandle); ! 224: VioWrtNCell (cefs(&c), N_of_Cols-sLen, WINDOW_TOP,sLen, VioHandle); 1.1 root 225: 226: if (sName[sLen-1] == '\\') 227: strcat (sName, "*.*"); 228: else 229: strcat (sName, "\\*.*"); 230: sHandle = -1; /* Family API only has one handle */ 231: sCount = 1; /* Search for one at a time */ 1.1.1.2 ! root 232: errCode = DosFindFirst (chfs(sName), ! 233: &sHandle, 1.1 root 234: DosAttrSubDir, 1.1.1.2 ! root 235: &sBuf, 1.1 root 236: sizeof(sBuf), 237: ufs(&sCount), 238: 0L); 239: while (!errCode) { 1.1.1.2 ! root 240: if (sBuf.achName[0] != '.') { /* Not a back link */ ! 241: if (sBuf.attrFile & DosAttrSubDir) { /* A subdirectory */ ! 242: newDir (&child, sBuf.achName, bfsHead); 1.1 root 243: insDir (bfsHead, child, &bfsTail); 244: bfsTail->d_link = child; 245: bfsTail = child; 246: } 247: } 1.1.1.2 ! root 248: errCode = DosFindNext (sHandle, ! 249: &sBuf, 1.1 root 250: sizeof(sBuf), 251: ufs(&sCount)); 252: } 1.1.1.2 ! root 253: DosFindClose (sHandle); 1.1 root 254: bfsHead = bfsHead->d_link; 255: } 256: } /* buildTree */ 257: 258: 259: /*** insDir - insert child directory into tree in alphabetical order 260: * 261: * 262: */ 263: insDir (par,child) 264: Directory *par; 265: Directory *child; 266: { 267: Directory *p,*q; 268: 269: p = par->d_child; /* p = first child */ 270: q = 0; /* q = previous pointer */ 271: while (p && (strcmp(child->d_name,p->d_name) > 0)) { 272: q = p; /* q = previous node */ 273: p = p->d_next; /* p = next node */ 274: } 275: if (!q) /* Insert at front of list */ 276: par->d_child = child; 277: else /* Insert at middle or end of list */ 278: q->d_next = child; 279: 280: child->d_prev = q; 281: child->d_next = p; 282: 283: if (p) /* Not inserting at end of list */ 284: p->d_prev = child; 285: } /* insDir */ 286: 287: 288: /*** newDir - create a new directory entry for tree 289: * 290: * 291: */ 292: newDir (dir,name,par) 293: Directory **dir; 1.1.1.2 ! root 294: NPCH name; 1.1 root 295: Directory *par; 296: { 297: Directory *p; 298: 299: p = (Directory *) malloc (sizeof(Directory)); 300: if (!p) { 301: fprintf (stderr, "\nOut of memory - Allocating directory node\n"); 302: exitError (2); 303: } 304: p->d_name[0] = '\0'; 305: strcpy (p->d_name,name); 306: p->d_parent = par; 307: p->d_prev = 0; 308: p->d_next = 0; 309: p->d_child = 0; 310: p->d_link = 0; 311: 312: *dir = p; /* Return address of new dir node */ 313: } /* newDir */ 314: 315: 316: /*** pruneTree - prune subtree that has been deleted 317: * 318: * Called when we discover that a directory no longer exists. 319: * 320: * ENTRY: root = address of pointer to directory node that has evaporated. 321: * 322: * EXIT: root = address of pointer to some other node that is "close" 323: * to the evaporated node. Choose previous, next, or 324: * parent, in that order. 325: */ 326: pruneTree (curDir) 327: Directory **curDir; 328: { 329: Directory *p; /* Used to traverse tree */ 330: Directory *q; /* Used to traverse tree */ 331: Directory *n; /* Node to return */ 332: 333: p = *curDir; /* p = node to delete */ 334: if (n = p->d_prev) { /* n = previous sibling */ 335: q = p->d_next; /* q = next for n */ 336: n->d_next = q; /* Point new node to new next */ 337: if (q) /* Not last sibling */ 338: q->d_prev = n; /* Point next back to new node */ 339: } 340: else /* No previous sibling */ 341: if (n = p->d_next) { /* n = next sibling */ 342: n->d_prev = 0; /* Next sibling is now first */ 343: q = n->d_parent; /* q = parent */ 344: q->d_child = n; /* Point parent to new first child */ 345: } 346: else 347: if (n = p->d_parent) /* n = parent */ 348: if (n->d_parent) /* n is not root */ 349: n->d_child = 0; /* Deleted only child of parent */ 350: else { 351: fprintf (stderr, "directory tree is empty\n"); 352: exit (2); 353: } 354: else { 355: fprintf (stderr, "directory tree is empty\n"); 356: exit (2); 357: }; 358: 359: delDir (p); /* Delete subtree */ 360: decorateTree (root); /* Re-build tree image */ 361: stateModified = TRUE; /* Tree is modified */ 362: *curDir = n; /* Return new node */ 363: 364: } /* pruneTree */ 365: 366: 367: /*** delDir - Delete directory subtree 368: * 369: * 370: */ 371: delDir (root) 372: Directory *root; 373: { 374: Directory *p; 375: Directory *q; 376: 377: p = root->d_child; /* p = first child */ 378: while (p) { /* Still children to delete */ 379: q = p; 380: p = p->d_next; 381: delDir (q); 382: } 383: 384: free ( (char *) root); 385: 386: } /* delDir */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.