home *** CD-ROM | disk | FTP | other *** search
/ CD-ROM Aktief 1995 #6 / CDA_6.iso / shell / utils / disked29.arj / SOURCE.ZIP / DIRENT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-19  |  15.2 KB  |  657 lines

  1. /***
  2. *dirent.c - disked disk directory maintenence.
  3. *
  4. *Copyright (c) 1993-1995, Gregg Jennings.  All wrongs reserved.
  5. *   P O Box 200, Falmouth, MA 02541-0200
  6. *
  7. *Purpose:
  8. *   Handles the displaying and editing of directory sectors.
  9. *
  10. *Notice:
  11. *   This progam may be freely used and distributed.  Any distrubution
  12. *   with modifications must retain the above copyright statement and
  13. *   modifications noted.
  14. *   No pulp-publication, in whole or in part, permitted without
  15. *   permission (magazines or books).
  16. *******************************************************************************/
  17.  
  18. /*
  19.    Versions:
  20.  
  21.    1.3   13-Nov-1993    more use of structures, cleaned up changedir()
  22.    1.2   14-Jan-1994    =0 bug fix in changedir()
  23.    1.1   13-Nov-1993    Started structures
  24.    1.0   June 1993
  25.  
  26.    Release Notes:
  27.  
  28.    This is all "Brute Force" code.  Written in a couple a days after
  29.    I wanted to arange all my directories is a certain non-sorted way
  30.    easier than a touch program.
  31. */
  32.  
  33. #include <stdio.h>
  34. #include <conio.h>
  35. #include <ctype.h>
  36.  
  37. #include "mylib.h"               /* getnum() */
  38. #include "keys.h"
  39. #include "dirent.h"              /* DosTime, DosDate, dDIR */
  40. #include "console.h"             /* input, output, cursor stuff */
  41.  
  42.  
  43. /* NO globals referenced here */
  44.  
  45. /* NO globals defined here */
  46.  
  47.  
  48. #define isexten(c) ( (c>0x7f) && (c<255) )
  49.  
  50. static int command(int c);
  51. static int text(int len, unsigned char *b);
  52. static int attrib(unsigned char *b);
  53. static int dostime(DosTime time, DosTime *t);
  54. static int dosdate(DosDate date, DosDate *d);
  55. static int pdirent(dDIR *);
  56.  
  57. /* ...filename.txt...ttri...hh:mm:ss...mm/dd/yy...1234567...1234567 */
  58. static char
  59. *dir_header="   File           Attr    Time       Date       Cluster      Size\n";
  60.  
  61. /* display directory */
  62.  
  63. extern void dumpdir(unsigned char *buf, int sec_size)
  64. {
  65. int i;
  66. dDIR *dir = (dDIR *)buf;
  67.  
  68.    output('\n');
  69.    output('\n');
  70.    print(dir_header);                        /* print header */
  71.  
  72.    for (i = 0; i < sec_size; i+=sizeof(dDIR),dir++)    /* and each entry */
  73.    {
  74.       output('\n');
  75.       put(3,' ');
  76.       pdirent(dir);
  77.    }
  78.    output('\n');
  79. }
  80.  
  81. /* change dir command structure */
  82.  
  83. /* ...filename.txt...ttri...hh:mm:ss...mm/dd/yy...1234567...1234567 */
  84. struct fields {
  85.    int beg;             /* starting column */
  86.    int end;             /* ending column */
  87.    int (*inp)();        /* function to do the change */
  88. } field[] = {
  89.    {4,7,  command},
  90.    {9,16, text},
  91.    {18,20,text},
  92.    {24,28,attrib},
  93.    {32,33,dostime},
  94.    {43,44,dosdate},
  95. };
  96.  
  97. /***
  98. *changedir() - edit directory entry(s) in sector buffer
  99. *
  100. *  ver 1.1  fixed =0 bug
  101. ****/
  102.  
  103.  
  104. #define NUMFIELDS    (sizeof(field)/sizeof(struct fields)-1)
  105. #define LASTENTRY    ((int)(sec_size/sizeof(dDIR))-1)
  106.  
  107. extern int changedir(unsigned char *buf,int sec_size)
  108. {
  109. int i;
  110. unsigned int a,x;
  111. unsigned int *b;
  112. unsigned int c;
  113. unsigned int n;
  114. int o;            /* offset into buffer (dDIR pointer) */
  115. int r;
  116. int p;            /* absolute position */
  117. int f;            /* field in  */
  118.  
  119.    get_cursor(&a,&x);
  120.    print("\n\n      %s",dir_header);
  121.  
  122.    i = r = 0;
  123.    for (;;)
  124.    {
  125.       c = f = 0;                     /* start off at command function */
  126.       p = field[f].beg;
  127.       print("\n%03d      ",i+1);
  128.  
  129.       o = i*sizeof(dDIR);
  130.       r = pdirent((dDIR *)(buf+o));
  131. get:
  132.       set_cursor(a,p);
  133.  
  134.       switch (f)
  135.       {
  136.          case 0:                                /* command */
  137.             c = (*field[f].inp)(r);             /* arg: entry type */
  138.             break;
  139.          case 1:                                /* file name */
  140.             c = (*field[f].inp)(8,buf+o);       /* args: length, char* */
  141.             break;
  142.          case 2:                                /* file extension */
  143.             c = (*field[f].inp)(3,buf+o+8);     /* args: length, char* */
  144.             break;
  145.          case 3:                                /* attribute */
  146.             c = (*field[f].inp)(buf+o+11);      /* arg: int* */   
  147.             break;
  148.          case 4:                                /* time */
  149.             b=(unsigned int *)(buf+o+0x16);     /* arg: DosTime* */
  150.             c = (*field[f].inp)(*b,b);
  151.             break;
  152.          case 5:                                /* date */
  153.             b=(unsigned int *)(buf+o+0x18);     /* arg: DosDate* */
  154.             c = (*field[f].inp)(*b,b);
  155.             break;
  156.       }
  157.  
  158.       /* deal with key returned from functions */
  159.  
  160.       switch (c)                 /* convert scancodes to ASCII */
  161.       {
  162.          case RIGHT:             /* next field */
  163.          case CRIGHT:
  164.             c = '\t';
  165.             break;
  166.          case SHTAB:             /* previous field */
  167.          case CLEFT:
  168.          case LEFT:
  169.             c = 0x7f;
  170.             break;
  171.          case DOWN:              /* next entry */
  172.             c = '\r';
  173.             break;
  174.          case UP:                /* previous entry */
  175.             c = '\b';
  176.             break;
  177.          default:
  178.             c &= 0xff;           /* convert to ASCII */
  179.             break;
  180.       }
  181.  
  182.       /* ASCII */
  183.  
  184.       switch (c)
  185.       {
  186.          case 0x7f:                                /* previous field */
  187.             if (f > 0)
  188.                p = field[--f].beg;
  189.             break;
  190.          case '\t':                                /* next field */
  191.             if (f < NUMFIELDS)
  192.                p = field[++f].beg;
  193.             break;
  194.          case '\r':
  195.          case ' ':                                 /* next entry */
  196.             if (i == LASTENTRY)                    /* if at end */
  197.             {                                      /*  wrap */  
  198.                i = 0;
  199.                print("\n\n      %s",dir_header);   /* redisplay header */
  200.             }
  201.             else
  202.                i++;
  203.             continue;                              /* redisplay entry */
  204.             break;
  205.          case '\b':                                /* previous entry */
  206.             if (i == 0)                            /* if at beginning */
  207.             {                                      /*  wrap */
  208.                i = LASTENTRY;
  209.                print("\n\n      %s",dir_header);   /* redisplay header */
  210.             }
  211.             else
  212.                i--;
  213.             continue;
  214.             break;
  215.          case '=':                                 /* select entry */
  216.             output(c);
  217.             if (getnum(sec_size/sizeof(dDIR),&n,10) > 0 && n > 0)
  218.                i = n-1;
  219.             continue;
  220.             break;
  221.          case '/':
  222.          case '?':
  223.             print("\n\n\tCR/SP  next file");
  224.             print("\n\tBS     previous file");
  225.             print("\n\tTAB    next field");
  226.             print("\n\tSHTAB  previous field");
  227.             print("\n\t=n     goto file n");
  228.             print("\n\t'C'    goto filename");
  229.             print("\n\t.|ESC  exit\n");
  230.             continue;
  231.             break;
  232.          case '.':
  233.          case ESC:
  234.             output('\n');
  235.             return 0;
  236.             break;
  237.          default: 
  238.             if (isalnum(c))                        /* letter? */
  239.             {
  240.                int j;
  241.                c = toupper(c);
  242.                for (j = i+1; ;j++)
  243.                {
  244.                   if (j > LASTENTRY)
  245.                      j = 0;
  246.                   if (*(buf+(j*sizeof(dDIR))) == c)
  247.                      break;
  248.                   if (j == i)
  249.                      break;
  250.                }
  251.                if (j != i)
  252.                {
  253.                   i = j;
  254.                   continue;
  255.                }
  256.             }
  257.             break;
  258.       }
  259.       goto get;
  260.    }
  261. }
  262.  
  263.  
  264. static int command(int c)
  265. {
  266. int i;
  267.  
  268.    i = scankey();
  269.    if (c < 1 && (i==RIGHT || i==TAB))
  270.       i = 0;
  271.    return i;
  272. }
  273.  
  274. /***
  275. *text() -- edit a text entry (filename/ext)
  276. *
  277. *  can enter ALL printable characters including '.' and ' '
  278. ****/
  279.  
  280. static int text(int len, unsigned char *buf)
  281. {
  282. int c;
  283. int i;
  284.  
  285.    for (i=0;;)
  286.    {
  287.       c=scankey();
  288.       if (c==RIGHT)
  289.       {
  290.          if (i==len-1)
  291.             break;
  292.          curright();
  293.          ++i;
  294.          continue;
  295.       }
  296.       if (c==LEFT || c==BACKSP)
  297.       {
  298.          if (!i)
  299.             break;
  300.          --i;
  301.          curleft();
  302.          continue;
  303.       }
  304.       if (c==RETURN || c==TAB || c==SHTAB || c==DOWN || c==UP)
  305.          break;
  306.       if (c==ESCAPE)
  307.          return(0);
  308.       if (c>0x352f) continue;
  309.       c&=0xff;
  310.       if (isgraph(c) || isexten(c))
  311.       {
  312.          *(buf+i)=(char)c;
  313.          i++;
  314.          output(c);
  315.          if (i==len)
  316.          {
  317.             c=RIGHT;
  318.             break;
  319.          }
  320.       }
  321.    }
  322.    return(c);
  323. }
  324.  
  325. /***
  326. *attrib() - toggle filename attributes, except for dir
  327. *
  328. ****/
  329.  
  330. static int attrib(unsigned char *buf)
  331. {
  332. int i;
  333. int b,c,p,d;
  334. byte isvol;
  335.  
  336.    /* 01234 */
  337.    /* RHSDA */
  338.  
  339.    isvol = (byte)(*buf&8);
  340.    b=d=p=0;                   /* no need to set d,b but it gets rid of */
  341.                               /*  MSC warning C4701 */
  342.    for (;;)
  343.    {
  344.       i=scankey();
  345.       if (i==RETURN || i==TAB || i==SHTAB || i==DOWN || i==UP)
  346.          break;
  347.       if (i==ESCAPE)
  348.       {
  349.          i=0;
  350.          break;
  351.       }
  352.       if (i==RIGHT)
  353.       {
  354.          if (p==4)      /* end */
  355.             break;
  356.          curright();
  357.          ++p;
  358.          continue;
  359.       }
  360.       if (i==LEFT || i==BACKSP)
  361.       {
  362.          if (p==0)
  363.             break;
  364.          --p;
  365.          curleft();
  366.          continue;
  367.       }
  368.  
  369.       if ( !isvol && p!=3 && (i&0xff)==' ')
  370.       {
  371.          if (p==0)
  372.          {
  373.             b=1;
  374.             d='R';
  375.          }
  376.          else if (p==1)
  377.          {
  378.             b=2;
  379.             d='H';
  380.          }
  381.          else if (p==2)
  382.          {
  383.             b=4;
  384.             d='S';
  385.          }
  386.          else if (p==4)
  387.          {
  388.             b=0x20;
  389.             d='A';
  390.          }
  391.          if (*buf&b)
  392.          {
  393.             c='_';
  394.             *buf&=~b;
  395.          }
  396.          else
  397.          {
  398.             c=d;
  399.             *buf|=b;
  400.          }
  401.          output(c);
  402.          curleft();
  403.       }
  404.    }
  405.    return(i);
  406. }
  407.  
  408. static int dostime(DosTime time, DosTime *t)
  409. {
  410. int i;
  411. int h,m,s;
  412. unsigned int r,x;
  413. int c,p;
  414.  
  415.    /* 01234567 */
  416.    /* hh:mm:ss */
  417.  
  418.    get_cursor(&r,&x);
  419.    c = x;                     /* set starting column */
  420.    p = c;                     /* set the working column pointer */
  421.  
  422.    h = time.hours;            /* set the working values */
  423.    m = time.minutes;
  424.    s = time.seconds;
  425.  
  426.    for (;;)
  427.    {
  428.       set_cursor(r,p);
  429.  
  430.       i=scankey();
  431.  
  432.       if (i==TAB || i==RETURN || i==SHTAB || i==DOWN || i==UP)
  433.          return(i);
  434.  
  435.       if (i==ESCAPE)
  436.       {
  437.          i=0;
  438.          break;
  439.       }
  440.  
  441.       if (i==LEFT || i==BACKSP)
  442.       {
  443.          if (p==c && i==LEFT)
  444.             return(i);
  445.          if (p==c && i==BACKSP)
  446.             continue;
  447.          if (p==c+3 || p==c+6)
  448.             p-=2;
  449.          else
  450.             p--;
  451.          continue;
  452.       }
  453. right:
  454.       if (i==RIGHT)
  455.       {
  456.          if (p==c+7)
  457.             return(i);
  458.          if (p==c+1 || p==c+4)
  459.             p+=2;
  460.          else
  461.             p++;
  462.          continue;
  463.       }
  464.       i&=0xff;
  465.       if (isdigit(i))
  466.       {
  467.          output(i);
  468.          i=i-'0';                   /* convert ascii to bin */
  469.  
  470.          /* based on column, */
  471.          /*  calculate new time with the */
  472.          /*  number input */
  473.  
  474.          if (p==c)
  475.             h=(i*10)+(h%10);
  476.          else if (p==c+1)
  477.             h=i+((h/10)*10);
  478.          else if (p==c+3)
  479.             m=(i*10)+(m%10);
  480.          else if (p==c+4)
  481.             m=i+((m/10)*10);
  482.          else if (p==c+6)
  483.             s=(i*10)+(s%10);
  484.          else if (p==c+7)
  485.             s=i+((s/10)*10);
  486.  
  487.          time.hours = h;
  488.          time.minutes = m;
  489.          time.seconds = s;
  490.          *t = time;
  491.  
  492.          i = RIGHT;
  493.          goto right;
  494.       }
  495.    }
  496.    return i;
  497. }
  498.  
  499. /***
  500. *dosdate() - edit date field
  501. *
  502. *  ver   1.1   fixed right arrow at last number from wrapping
  503. ****/
  504.  
  505. static int dosdate(DosDate date, DosDate *dt)
  506. {
  507. int i;
  508. int m,d,y;
  509. unsigned int r,x;
  510. int c,p;
  511.  
  512.    /* 01234567 */
  513.    /* mm/dd/yy */
  514.  
  515.    get_cursor(&r,&x);
  516.    c = x;
  517.    p = c;
  518.    m = date.month;
  519.    d = date.day;
  520.    y = date.year+80;
  521.  
  522.    for (;;)
  523.    {
  524.       set_cursor(r,p);
  525.       i=scankey();
  526.  
  527.       if (i==TAB || i==RETURN || i==SHTAB || i==DOWN || i==UP)
  528.          break;
  529.  
  530.       if (i==ESCAPE)
  531.          return 0;
  532.  
  533.       if (i==LEFT || i==BACKSP)
  534.       {
  535.          if (p==c && i==LEFT)
  536.             return(i);
  537.          if (p==c && i==BACKSP)
  538.             continue;
  539.          if (p==c+3 || p==c+6)
  540.             p-=2;
  541.          else
  542.             p--;
  543.          continue;
  544.       }
  545. right:
  546.       if (i==RIGHT)
  547.       {
  548.          if (p==c+7)
  549.             continue;
  550.          if (p==c+1 || p==c+4)
  551.             p+=2;
  552.          else
  553.             p++;
  554.          continue;
  555.       }
  556.       i&=0xff;
  557.       if (isdigit(i))
  558.       {
  559.          output(i);
  560.          i=i-'0';
  561.  
  562.          if (p==c)
  563.             m=(i*10)+(m%10);
  564.          else if (p==c+1)
  565.             m=i+((m/10)*10);
  566.          else if (p==c+3)
  567.             d=(i*10)+(d%10);
  568.          else if (p==c+4)
  569.             d=i+((d/10)*10);
  570.          else if (p==c+6)
  571.             y=(i*10)+(y%10);
  572.          else if (p==c+7)
  573.             y=i+((y/10)*10);
  574.          if (y>80)
  575.             y-=80;
  576.          else
  577.             y=0;
  578.  
  579.          date.month = m;
  580.          date.day = d;
  581.          date.year = y;
  582.          y += 80;
  583.          *dt = date;
  584.  
  585.          i=RIGHT;
  586.          goto right;
  587.       }
  588.    }
  589.    return i;
  590. }
  591.  
  592. /***
  593. *pdirent() - print directory entry
  594. *
  595. *  Returns: 0 unused, 1 normal, -1 for directory or erased
  596. *
  597. *  1.2   11/12/94    references a dDIR structure, can't edit '.' dirs
  598. * v1.1   removed superfluous pointer
  599. ****/
  600.  
  601. static int pdirent(dDIR *dir)
  602. {
  603. int i,r;
  604. unsigned char c;
  605.  
  606.    r = 1;
  607.    if (dir->name[0] == 0)
  608.    {
  609.       print(" unused");
  610.       r = 0;
  611.    }
  612.    else
  613.    {
  614.       /* set can't edit return flag */
  615.  
  616.       if (dir->name[0] == 0xE5 || dir->name[0] == '.')
  617.          r = -1;
  618.  
  619.       /* check for bad chars in case and non-dir sector is displayed */
  620.  
  621.       for (i = 0; i < 8; i++)
  622.       {
  623.          c = dir->name[i];
  624.          if (isspace((int)c) || c==255 || !c || c==7 || c==8)
  625.             output(' ');
  626.          else
  627.             output(c);
  628.       }
  629.       output('.');
  630.       for (i = 0; i < 3; i++)
  631.       {
  632.          c = dir->ext[i];
  633.          if (isspace((int)c) || c==255 || !c || c==7 || c==8)
  634.             output(' ');
  635.          else
  636.             output(c);
  637.       }
  638.       print("   ");
  639.       if (dir->attr.volume)
  640.          print(" Vol ");
  641.       else
  642.       {
  643.          output(dir->attr.rdonly ? 'R' : '_');
  644.          output(dir->attr.hidden ? 'H' : '_');
  645.          output(dir->attr.system ? 'S' : '_');
  646.          output(dir->attr.subdir ? 'D' : '_');
  647.          output(dir->attr.archiv ? 'A' : '_');
  648.       }
  649.       print("   %02d:%02d:%02d",dir->time.hours,dir->time.minutes,dir->time.seconds);
  650.       print("   %02d/%02d/%02d",dir->date.month,dir->date.day,dir->date.year+80);
  651.       print("   % 7u",dir->start);
  652.       if (!dir->attr.subdir)
  653.          print("   % 7lu",dir->size);
  654.    }
  655.    return r;
  656. }
  657.