Annotation of os2sdk/demos/apps/ds/tree.c, revision 1.1.1.2

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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.