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

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

unix.superglobalmegacorp.com

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