home *** CD-ROM | disk | FTP | other *** search
/ vsiftp.vmssoftware.com / VSIPUBLIC@vsiftp.vmssoftware.com.tar / FREEWARE / FREEWARE40.ZIP / flistfrontend / src / flsort.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-25  |  16.0 KB  |  408 lines

  1. #ifndef NO_IDENT
  2. static char *Id = "$Id: flsort.c,v 1.11 1995/10/25 13:39:18 tom Exp $";
  3. #endif
  4.  
  5. /*
  6.  * Title:    flsort.c - "FLIST" sorting
  7.  * Author:    T.E.Dickey
  8.  * Created:    04 May 1984
  9.  * Last update:
  10.  *        24 Oct 1995    added USER-sort
  11.  *        18 Mar 1995    prototypes
  12.  *        18 Feb 1995    port to AXP (DATENT mods).
  13.  *        02 Jan 1989    modified to use 'qsort' instead of my selection-
  14.  *                sort.
  15.  *        04 Nov 1988    added sort for expired-date.
  16.  *        24 Sep 1985    don't need to upper-case 'xdcl_' stuff
  17.  *        29 Aug 1985    corrected handling of /SWEEK if applied to the
  18.  *                backup date.
  19.  *        29 Jul 1985    assume 'filelink' pointer is unique for resetting
  20.  *                selection-entry.
  21.  *        03 Jul 1985    cleanup 'filelist' definition.
  22.  *        04 May 1985    renamed from 'dirsrt', made it called from
  23.  *                'dircmd' rather than indirectly via main-code.
  24.  *        22 Mar 1985    added IDENTIFIER, LENGTH
  25.  *        09 Jan 1985    nailed down column-suppression, fixed ordering
  26.  *                for TYPE-sort.
  27.  *        29 Dec 1984    added BACKUP, CREATED, REVISED and WEEK
  28.  *        22 Dec 1984    renamed ATTRIBUTE to XAB (for ALLOC).
  29.  *        11 Dec 1984    added FORMAT, ATTRIBUTE sorting, moved HOUR
  30.  *                decoding into this module.
  31.  *        13 Sep 1984    corrected permission to sort OWNER
  32.  *        03 Sep 1984    use "import"
  33.  *        27 Aug 1984    corrected no-action exit
  34.  *        15 Aug 1984    separated CREATED,BACKUP,REVISED dates
  35.  *        06 Aug 1984    added sort-by-hour
  36.  *        05 Aug 1984    use VMS-C structure-copy feature.
  37.  *        15 Jul 1984    sort paths via sequence key
  38.  *        14 Jul 1984    added OWNER-sort, enhanced warnings
  39.  *        20 Jun 1984    Do fixed-point sort (uses 'dircmd_select()')
  40.  *        19 Jun 1984    to add "Sorting..." message.
  41.  *        14 May 1984
  42.  *
  43.  * Function:    This module performs the directory-sorting operations for
  44.  *        the "FLIST" program.  The following fields are sortable:
  45.  *
  46.  *        P    path,name,type,vers
  47.  *        N    name,type,vers,path (normal)
  48.  *        T    type,name,vers,path
  49.  *        V    vers,name,type,path
  50.  *
  51.  *        A    alloc    [,name,type,vers,path]
  52.  *        B    backup    [,name,type,vers,path]
  53.  *        C    created    [,name,type,vers,path]
  54.  *        D    date    [,name,type,vers,path]
  55.  *        E    expir    [,name,type,vers,path]
  56.  *        F    format    [,name,type,vers,path]
  57.  *        H    hour    [,name,type,vers,path]
  58.  *        M    protect    [,name,type,vers,path]
  59.  *        O    owner    [,name,type,vers,path]
  60.  *        R    revised    [,name,type,vers,path]
  61.  *        S    size    [,name,type,vers,path]
  62.  *        U    user    [,name,type,vers,path]
  63.  *        W    week    [,name,type,vers,path]
  64.  *        X    xab    [,name,type,vers,path]
  65.  *
  66.  * Parameters:    opt -      alphabetic code (see above)
  67.  *        order -      normal/reverse flag (TRUE = reverse).
  68.  *        curfile - index into 'filelist[]' of current file
  69.  *        fix -     temporarily "fix" the current location, restoring the
  70.  *              original file-entry which may have been selected.
  71.  *
  72.  * Returns:    The index into 'filelist[]' at which the cursor should be
  73.  *        placed after the sort.  If the sort is not applicable (because
  74.  *        no data was read for this purpose), the original index is
  75.  *        returned.  Because a 'dds_pack' is performed for all applicable
  76.  *        sort operations, the file-index may be adjusted even if no
  77.  *        changes result directly from the sort.
  78.  */
  79.  
  80. #include    <stdlib.h>    /* declares 'qsort()' */
  81. #include    <ctype.h>
  82. #include    <string.h>
  83.  
  84. #include    <lib$routines.h>
  85. #include    <rmsdef.h>
  86.  
  87. #include    "flist.h"
  88. #include    "dircmd.h"
  89. #include    "dds.h"
  90.  
  91. #include    "sysutils.h"
  92.  
  93. import(filelist); import(numfiles);
  94. import(A_opt);    import(D_opt);    import(M_opt);    import(O_opt);
  95.  
  96. static
  97. char    *full_opt[] = {
  98.         "PATH",        "NAME",        "TYPE",        "VERSION",
  99.         "ALLOC",    "BACKUP",    "CREATED",    "DATE",
  100.         "EXPIRED",
  101.         "FORMAT",    "HOUR",        "MASK",        "OWNER",
  102.         "REVISED",    "SIZE",        "USER",
  103.         "XAB"};
  104. static
  105. int    by_hour = 0;        /* Last HOUR-mode used    */
  106.  
  107. static    int    flsort_fix (FLINK *f_);
  108.  
  109. /*
  110.  * The following sort-definitions return -1 if the first argument is lower,
  111.  * 0 if equal, +1 if greater.  Definitions are used rather than procedures
  112.  * to try to make this code run as rapidly as possible (though larger).
  113.  *
  114.  * Notes:
  115.  *    1. Strings are sorted in the opposite sense (increasing order)
  116.  *       to the sense of the size, date, protection codes.
  117.  *    2. Even though the filetype is only three bytes, I must use 'strcmp'
  118.  *       to compare it, because the ordering of bytes on VAX puts the left
  119.  *       character in the least significant position.
  120.  */
  121.  
  122. #define    LSS    -1
  123. #define    GTR    1
  124. #define    EQL    0
  125.  
  126. #define    hi(z)        (z.date64[1])
  127. #define    lo(z)        (z.date64[0])
  128.  
  129. #define    sort_FWD(n1,n2)    (cmp = ((n1 < n2) ? LSS : ((n1 > n2) ? GTR : EQL)))
  130. #define    sort_NUM(n1,n2)    (cmp = ((n1 < n2) ? GTR : ((n1 > n2) ? LSS : EQL)))
  131.  
  132. #define    sort_STR(s1,s2) (cmp = strcmp(s1, s2))
  133.  
  134. #define    sort_P(z1,z2)    sort_FWD(z1->fpath_->path_sort, z2->fpath_->path_sort)
  135. #define    sort_N(z1,z2)    sort_STR(z1->fname,  z2->fname)
  136. #define    sort_T(z1,z2)    sort_STR(z1->ftype,  z2->ftype)
  137. #define    sort_U(z1,z2)    sort_STR(z1->f_user, z2->f_user)
  138.  
  139. #define    sort_V(z1,z2)    sort_NUM(z1->fvers,  z2->fvers)
  140.  
  141. #ifdef __alpha
  142. #define    sort_D(z1,z2)    sort_NUM(z1,z2)
  143. #else
  144. #define    sort_D(z1,z2)    (sort_NUM(hi(z1),hi(z2)) ? cmp :\
  145.              sort_NUM(lo(z1),lo(z2)))
  146. #endif
  147.  
  148. #define    sort_H(z1,z2)    sort_NUM(z1->fhour,  z2->fhour)
  149.  
  150. #define    sort_S(z1,z2)    sort_NUM(z1->fsize,  z2->fsize)
  151. #define    sort_A(z1,z2)    sort_NUM(z1->fallc,  z2->fallc)
  152. #define    sort_M(z1,z2)    sort_NUM(z1->fprot,  z2->fprot)
  153. #define    sort_O(z1,z2)    (sort_FWD(z1->f_grp, z2->f_grp) ? cmp :\
  154.              sort_FWD(z1->f_mbm, z2->f_mbm))
  155. #define    sort_F(z1,z2)    sort_NUM(z1->f_rfm,  z2->f_rfm)
  156. #define    sort_X(z1,z2)    sort_NUM(z1->f_rat,  z2->f_rat)
  157.  
  158. /*
  159.  * Define sorting for file entries which cannot be fully displayed, due to
  160.  * privilege violation (SIZE, DATE, MASK and OWNER are affected):
  161.  */
  162. #define    sortPRV(z1,z2)    (cmp = (zNOPRIV(z1) ? (zNOPRIV(z2) ? EQL : GTR)\
  163.                         : (zNOPRIV(z2) ? LSS : EQL) ))
  164.  
  165. static    int    sortopt,    /* copy of 'opt' */
  166.         sortord;    /* copy of 'order' */
  167.  
  168. static
  169. int    compare(const void *p1, const void *p2)
  170. {
  171.     register FILENT    *f1    = &((*(FLINK **)p1)->fk),
  172.             *f2    = &((*(FLINK **)p2)->fk);
  173.     register int    cmp    = 0;
  174.  
  175.     switch (sortopt)
  176.     {
  177.     case 'P':
  178.         if (sort_P(f1,f2))    break;
  179.         if (sort_N(f1,f2))    break;
  180.         if (sort_T(f1,f2))    break;
  181.         sort_V(f1,f2);
  182.         break;
  183.     case 'T':
  184.         if (sort_T(f1,f2))    break;
  185.         if (sort_N(f1,f2))    break;
  186.         if (sort_P(f1,f2))    break;
  187.         sort_V(f1,f2);
  188.         break;
  189.     case 'V':
  190.         if (sort_V(f1,f2))    break;
  191.         goto by_name;
  192.     case 'S':
  193.         if (sortPRV(f1,f2))    break;
  194.         if (sort_S(f1,f2))    break;
  195.         goto by_name;
  196.  
  197.     case 'A':
  198.         if (sortPRV(f1,f2))    break;
  199.         if (sort_A(f1,f2))    break;
  200.         goto by_name;
  201.  
  202.     case 'C':            /* CREATED    */
  203.         if (sortPRV(f1,f2))    break;
  204.         if (sort_D(f1->fdate,f2->fdate))    break;
  205.         goto by_name;
  206.     case 'B':            /* BACKUP    */
  207.         if (sortPRV(f1,f2))    break;
  208.         if (sort_D(f1->fback,f2->fback))    break;
  209.         goto by_name;
  210.     case 'R':            /* REVISED    */
  211.         if (sortPRV(f1,f2))    break;
  212.         if (sort_D(f1->frevi,f2->frevi))    break;
  213.         goto by_name;
  214.     case 'E':            /* EXPIRED    */
  215.         if (sortPRV(f1,f2))    break;
  216.         if (sort_D(f1->fexpr,f2->fexpr))    break;
  217.         goto by_name;
  218.  
  219.     case 'H':
  220.         if (sortPRV(f1,f2))    break;
  221.         if (sort_H(f1,f2))    break;
  222.         goto by_name;
  223.     case 'M':
  224.         if (sortPRV(f1,f2))    break;
  225.         if (sort_M(f1,f2))    break;
  226.         goto by_name;
  227.     case 'O':
  228.         if (sortPRV(f1,f2))    break;
  229.         if (sort_O(f1,f2))    break;
  230.         goto by_name;
  231.     case 'U':
  232.         if (sortPRV(f1,f2))    break;
  233.         if (sort_U(f1,f2))    break;
  234.         goto by_name;
  235.     case 'I':
  236. #define    sort_ID(n)    sort_NUM(f1->fidnum[n],f2->fidnum[n])
  237.         if (sort_ID(0))        break;
  238.         if (sort_ID(1))        break;
  239.         if (sort_ID(2))        break;
  240.         goto by_name;
  241.  
  242.     case 'L':
  243.         if (sort_NUM(f1->f_recl,f2->f_recl))    break;
  244.         goto by_name;
  245.  
  246.     case 'F':
  247.         if (sortPRV(f1,f2))    break;
  248.         if (sort_F(f1,f2))    break;
  249.         goto by_name;
  250.     /* Sort XAB within FORMAT for better ordering    */
  251.     case 'X':
  252.         if (sortPRV(f1,f2))    break;
  253.         if (sort_F(f1,f2))    break;
  254.         if (sort_X(f1,f2))    break;
  255.     /* Continue into NAME after numeric sorts:    */
  256.     by_name:
  257.     default:
  258.         if (sort_N(f1,f2))    break;
  259.         if (sort_T(f1,f2))    break;
  260.         if (sort_P(f1,f2))    break;
  261.         if (sortopt != 'V')    sort_V(f1,f2);
  262.     }
  263.     return ((sortord > 0) ? cmp : -cmp);
  264. }
  265.  
  266. tDIRCMD(flsort)
  267. {
  268.     FLINK    *cmpFIX, *cmpTMP;
  269.     int    opt    = xdcl_->dcl_text[1],
  270.         order    = (xdcl_->dcl_text[0] == 'S') ? GTR : LSS,
  271.         fixpoint = dircmd_select(-2),    /* Save original selection-index */
  272.         j0, j1,
  273.         k0    = numfiles-1, k1,
  274.         cmp, got,
  275.         didsome    = 0,
  276.         lpp2    = crt_lpp() - 1;
  277.     DATENT    *c_;
  278.  
  279.     /* Verify that the option is legal one: */
  280.     if (! isprint (opt))
  281.         opt = 'N';
  282.  
  283.     for (j0 = 0; j0 < SIZEOF(full_opt); j0++)
  284.     {
  285.         if (opt == *full_opt[j0])
  286.             break;
  287.     }
  288.     if (j0 == SIZEOF(full_opt))    j0 = 1;    /* Coerce to NAME    */
  289.  
  290.     if ((strchr("AS",    opt)    && !A_opt)
  291.     ||  (strchr("BCDEHRW",    opt)    && !D_opt)
  292.     ||  (strchr("M",    opt)    && !M_opt)
  293.     ||  (strchr("OU",    opt)    && !O_opt) )
  294.     {
  295.         warn ("Sort (%s) is not applicable", full_opt[j0]);
  296.         return;
  297.     }
  298.  
  299.     if (opt == 'D')
  300.     {
  301.         switch (D_opt)
  302.         {
  303.         case 3:        opt = 'R';    break;
  304.         case 2:        opt = 'B';    break;
  305.         default:    opt = 'C';
  306.         }
  307.     }
  308.  
  309.     if (numfiles > 24)    dds_while (nullC);
  310.  
  311.     /*
  312.      * If we do a sort-by-hour, update the '.fhour' components to match
  313.      * the current date-selection option.  We use the same field for
  314.      * sort-by-day-of-week, since the two can't be combined anyway.
  315.      */
  316.     if (strchr("HW", opt))
  317.     {
  318.         got = (opt == 'H') ? D_opt : -D_opt;
  319.         cmp = (by_hour != got);
  320.         for (j0 = 0; j0 < numfiles; j0++)
  321.         {
  322.         if (!DELETED(j0) && !NOPRIV(j0))
  323.         {
  324.             switch (D_opt)
  325.             {
  326.             case 4:    c_ = &(FK(j0).fexpr);    break;
  327.             case 3:    c_ = &(FK(j0).frevi);    break;
  328.             case 2:    c_ = &(FK(j0).fback);    break;
  329.             default:    c_ = &(FK(j0).fdate);
  330.             }
  331.             if (cmp || ! FK(j0).fhour)
  332.             {
  333.             if (isBigDate(c_))
  334.                 FK(j0).fhour = 0xffff; /* biggest possible */
  335.             else
  336.             {
  337.                 if (opt == 'H')
  338.                 FK(j0).fhour = syshour(c_) >> 16;
  339.                 else
  340.                 {
  341.                 lib$day (&j1, c_);
  342.                 FK(j0).fhour = ((j1 + 3) % 7) + 1;
  343.                 }
  344.             }
  345.             }
  346.         }
  347.         }
  348.         by_hour    = got;
  349.         opt    = 'H';
  350.     }
  351.  
  352.     if (fixpoint >= 0)    cmpFIX    = filelist[fixpoint];
  353.     if (fix)        cmpTMP    = filelist[*curfile_];
  354.  
  355.     didsome = dds_pack (curfile_, TRUE); /* Get rid of all deleted files */
  356.     sortopt = opt;        /* set global needed in 'compare()' */
  357.     sortord = order;
  358.  
  359.     qsort(filelist, numfiles, sizeof(filelist[0]), compare);
  360.     didsome++;    /* for this sort, always scroll to beginning */
  361.  
  362.     /*
  363.      * If I did a fixed-point search, find the new position of the entry,
  364.      * and:
  365.      *    (a) Reset the index to the new position, and
  366.      *    (b) Reset (if required) the top/bottom file indices to permit
  367.      *        me to show this screen next.  The screen refresh is made
  368.      *        complicated because of the compaction which may have been
  369.      *        made with 'dds_pack()'.
  370.      *
  371.      * If I didn't do a fixed-sort, reset the current-file to the top-of
  372.      * list.
  373.      */
  374.     if (didsome)
  375.     {
  376.         if (fixpoint >= 0 || fix)
  377.         {
  378.             if (fixpoint >= 0)
  379.                 dircmd_select (*curfile_ = flsort_fix (cmpFIX));
  380.             if (fix)
  381.                 *curfile_ = flsort_fix (cmpTMP);
  382.  
  383.             k0 = lpp2 * (*curfile_ / lpp2); /* Nominal top-screen  */
  384.             k1 = numfiles - lpp2;     /* Try a better estimate   */
  385.             if (k1 >= 0 && k1 <= *curfile_)    k0 = k1;
  386.             dds_all (k0, *curfile_);
  387.         }
  388.         else
  389.             dds_all (0, *curfile_ = 0);
  390.     }
  391.     else
  392.         warn ("No change in sort-order");
  393. }
  394.  
  395. /*
  396.  * Return the present index of a particular FILENT entry in the 'filelist[]'
  397.  * array.
  398.  */
  399. static
  400. int    flsort_fix (FLINK *f_)
  401. {
  402.     int    j;
  403.  
  404.     for (j = 0; j < numfiles; j++)
  405.         if (f_ == filelist[j])        return (j);
  406.     return (-1);
  407. }