home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / os2sdk / os2sdk10 / apps / ds / tree.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-08-11  |  9.2 KB  |  385 lines

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