home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: WPS_PM / WPS_PM.zip / xfld085s.zip / main / cnrsort.c < prev    next >
C/C++ Source or Header  |  1999-02-23  |  17KB  |  479 lines

  1.  
  2. /*
  3.  *@@sourcefile cnrsort.c:
  4.  *      This file contains the new folder sort comparison functions only.
  5.  *      It is used by the new sort methods in xfldr.c.
  6.  *
  7.  *      For introductory information on how XFolder extended sorting
  8.  *      is implemented, refer to the XFolder programming guide.
  9.  *
  10.  *      This file was called "xfsort.c" in V0.80.
  11.  *
  12.  *      When sorting a container, one has to provide comparison
  13.  *      functions which will be called by PM's internal sort
  14.  *      algorithm (I don't know if it's a quicksort or whatever,
  15.  *      but this doesn't matter anyway). In other words, one does
  16.  *      _not_ have to write some sort algorithm oneself,
  17.  *      but only provides a comparision function.
  18.  *
  19.  *      These functions are used in two contexts:
  20.  *      1)  with the CM_SORTRECORD msg for sorting just once;
  21.  *      2)  in the CNRINFO.pSortRecord field, when a container
  22.  *          should always be sorted.
  23.  *
  24.  *      Sort comparison functions need to be like this:
  25.  +          SHORT EXPENTRY fnCompareExt(PMINIRECORDCORE pmrc1,
  26.  +                                      PMINIRECORDCORE pmrc2,
  27.  +                                      PVOID pStorage)
  28.  *
  29.  *      All these sort functions are used by XFolder in the context
  30.  *      of the extended sort functions. All the "pmrc" parameters
  31.  *      therefore point to WPS MINIRECORDCOREs (not RECORDCOREs). To
  32.  *      compare object titles, we can simply use the pszIcon fields.
  33.  *      If we need the actual SOM objects, we can use the
  34.  *      OBJECT_FROM_PREC macro.
  35.  *
  36.  *      Note: the information in the PM reference is flat out wrong.
  37.  *      Container sort functions need to return the following:
  38.  +          0   pmrc1 == pmrc2
  39.  +         -1   pmrc1 <  pmrc2
  40.  +         +1   pmrc1 >  pmrc2
  41.  *
  42.  *@@include #define INCL_WINSTDCNR
  43.  *@@include #include <os2.h>
  44.  *@@include #include "cnrsort.h"
  45.  */
  46.  
  47. /*
  48.  *      Copyright (C) 1997-99 Ulrich Möller.
  49.  *      This file is part of the XFolder source package.
  50.  *      XFolder is free software; you can redistribute it and/or modify
  51.  *      it under the terms of the GNU General Public License as published
  52.  *      by the Free Software Foundation, in version 2 as it comes in the
  53.  *      "COPYING" file of the XFolder main distribution.
  54.  *      This program is distributed in the hope that it will be useful,
  55.  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  56.  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  57.  *      GNU General Public License for more details.
  58.  */
  59.  
  60. #include <stdio.h>
  61. #define INCL_WIN
  62. #include <os2.h>
  63.  
  64. #pragma hdrstop
  65. #include <wpfolder.h>      // WPFolder
  66. #include <wpshadow.h>      // WPShadow
  67.  
  68. /*
  69.  *@@ fnCompareExt:
  70.  *      container sort comparison function for
  71.  *      sorting records by file name extension.
  72.  */
  73.  
  74. SHORT EXPENTRY fnCompareExt(PMINIRECORDCORE pmrc1, PMINIRECORDCORE pmrc2, PVOID pStorage)
  75. {
  76.     HAB habDesktop = WinQueryAnchorBlock(HWND_DESKTOP);
  77.     SHORT src = 0;
  78.  
  79.     pStorage = pStorage; // to keep the compiler happy
  80.  
  81.     if ((pmrc1) && (pmrc2))
  82.         if ((pmrc1->pszIcon) && (pmrc2->pszIcon))
  83.         {
  84.             // find last dot char in icon titles;
  85.             // strrchr finds LAST occurence (as opposed to strchr)
  86.             PSZ pDot1 = strrchr(pmrc1->pszIcon, '.');
  87.             PSZ pDot2 = strrchr(pmrc2->pszIcon, '.');
  88.             if (pDot1 == NULL)
  89.                 if (pDot2 == NULL)
  90.                     // both titles have no extension: return names comparison
  91.                     switch (WinCompareStrings(habDesktop, 0, 0,
  92.                             pmrc1->pszIcon, pmrc2->pszIcon, 0))
  93.                     {
  94.                         case WCS_LT: src = -1; break;
  95.                         case WCS_GT: src = 1; break;
  96.                         default: src = 0; break;
  97.                     }
  98.                 else
  99.                     // pmrc1 has no ext, but pmrc2 does:
  100.                     src = -1;
  101.             else
  102.                 if (pDot2 == NULL)
  103.                     // pmrc1 has extension, but pmrc2 doesn't:
  104.                     src = 1;
  105.                 else {
  106.                     // both records have extensions:
  107.                     // compare extensions
  108.                     switch (WinCompareStrings(habDesktop, 0, 0,
  109.                             pDot1, pDot2, 0))
  110.                     {
  111.                         case WCS_LT: src = -1; break;
  112.                         case WCS_GT: src = 1; break;
  113.                         default:
  114.                             // same ext: compare names
  115.                             switch (WinCompareStrings(habDesktop, 0, 0,
  116.                                     pmrc1->pszIcon, pmrc2->pszIcon, 0))
  117.                             {
  118.                                 case WCS_LT: src = -1; break;
  119.                                 case WCS_GT: src = 1; break;
  120.                                 default: src = 0; break;
  121.                             }
  122.                     }
  123.                 }
  124.         // printf("psz1: %s, psz2: %s --> %d\n", pmrc1->pszIcon, pmrc2->pszIcon, src);
  125.         }
  126.  
  127.     return (src);
  128. }
  129.  
  130. /*
  131.  *@@ fnCompareFoldersFirst:
  132.  *      container sort comparison function for
  133.  *      sorting folders first.
  134.  */
  135.  
  136. SHORT EXPENTRY fnCompareFoldersFirst(PMINIRECORDCORE pmrc1, PMINIRECORDCORE pmrc2, PVOID pStorage)
  137. {
  138.     HAB habDesktop = WinQueryAnchorBlock(HWND_DESKTOP);
  139.     pStorage = pStorage; // to keep the compiler happy
  140.     if ((pmrc1) && (pmrc2))
  141.         if ((pmrc1->pszIcon) && (pmrc2->pszIcon))
  142.         {
  143.             // get SOM objects from cnr record cores
  144.             WPObject *pObj1 = OBJECT_FROM_PREC(pmrc1);
  145.             WPObject *pObj2 = OBJECT_FROM_PREC(pmrc2);
  146.             if ((pObj1) && (pObj2))
  147.             {
  148.                 // determine if the objects are either folders
  149.                 // or shadows of folders
  150.                 BOOL IsFldr1 = _somIsA(pObj1, _WPFolder)
  151.                             ? TRUE
  152.                             : (_somIsA(pObj1, _WPShadow)
  153.                                 ? (_somIsA(_wpQueryShadowedObject(pObj1, TRUE), _WPFolder))
  154.                                 : FALSE
  155.                             );
  156.                 BOOL IsFldr2 = _somIsA(pObj2, _WPFolder)
  157.                             ? TRUE
  158.                             : (_somIsA(pObj2, _WPShadow)
  159.                                 ? (_somIsA(_wpQueryShadowedObject(pObj2, TRUE), _WPFolder))
  160.                                 : FALSE
  161.                             );
  162.                 if (IsFldr1)
  163.                     if (IsFldr2)
  164.                         // both are folders: compare titles
  165.                         switch (WinCompareStrings(habDesktop, 0, 0,
  166.                                 pmrc1->pszIcon, pmrc2->pszIcon, 0))
  167.                         {
  168.                             case WCS_LT: return (-1);
  169.                             case WCS_GT: return (1);
  170.                             default: return (0);
  171.                         }
  172.                     else
  173.                         // pmrc1 is folder, pmrc2 is not
  174.                         return (-1);
  175.                 else
  176.                     if (IsFldr2)
  177.                         // pmrc1 is NOT a folder, but pmrc2 is
  178.                         return (1);
  179.                     else
  180.                         // both are NOT folders: compare titles
  181.                         switch (WinCompareStrings(habDesktop, 0, 0,
  182.                                 pmrc1->pszIcon, pmrc2->pszIcon, 0))
  183.                         {
  184.                             case WCS_LT: return (-1);
  185.                             case WCS_GT: return (1);
  186.                             default: return (0);
  187.                         }
  188.             }
  189.         }
  190.     return (0);
  191. }
  192.  
  193. /*
  194.  *@@ fnCompareName:
  195.  *      comparison func for sort by name. This is
  196.  *      not terribly fast because it keeps using
  197.  *      WinCompareStrings, but at least this will
  198.  *      get special national characters right, which
  199.  *      the C library funcs won't.
  200.  */
  201.  
  202. SHORT EXPENTRY fnCompareName(PMINIRECORDCORE pmrc1, PMINIRECORDCORE pmrc2, PVOID pStorage)
  203. {
  204.     HAB habDesktop = WinQueryAnchorBlock(HWND_DESKTOP);
  205.     pStorage = pStorage; // to keep the compiler happy
  206.     if ((pmrc1) && (pmrc2))
  207.         if ((pmrc1->pszIcon) && (pmrc2->pszIcon))
  208.             switch (WinCompareStrings(habDesktop, 0, 0,
  209.                 pmrc1->pszIcon, pmrc2->pszIcon, 0))
  210.             {
  211.                 case WCS_LT: return (-1);
  212.                 case WCS_GT: return (1);
  213.             }
  214.  
  215.     return (0);
  216. }
  217.  
  218. /*
  219.  *@@ fnCompareType:
  220.  *      comparison func for sort by type (.TYPE EA)
  221.  */
  222.  
  223. SHORT EXPENTRY fnCompareType(PMINIRECORDCORE pmrc1, PMINIRECORDCORE pmrc2, PVOID pStorage)
  224. {
  225.     HAB habDesktop = WinQueryAnchorBlock(HWND_DESKTOP);
  226.     pStorage = pStorage; // to keep the compiler happy
  227.     if ((pmrc1) && (pmrc2))
  228.         if ((pmrc1->pszIcon) && (pmrc2->pszIcon))
  229.         {
  230.             // get SOM objects from cnr record cores
  231.             WPObject *pObj1 = OBJECT_FROM_PREC(pmrc1);
  232.             WPObject *pObj2 = OBJECT_FROM_PREC(pmrc2);
  233.             PSZ pType1 = NULL, pType2 = NULL;
  234.             if ((pObj1) && (pObj2))
  235.             {
  236.                 if (_somIsA(pObj1, _WPFileSystem))
  237.                     pType1 = _wpQueryType(pObj1);
  238.                 if (_somIsA(pObj2, _WPFileSystem))
  239.                     pType2 = _wpQueryType(pObj2);
  240.  
  241.                 if (pType1) {
  242.                     if (pType2)
  243.                         switch (WinCompareStrings(habDesktop, 0, 0,
  244.                             pType1, pType2, 0))
  245.                         {
  246.                             case WCS_LT: return (-1);
  247.                             case WCS_GT: return (1);
  248.                         }
  249.                     else
  250.                         // obj1 has type, obj2 has not
  251.                         return (-1);
  252.                 } else
  253.                     if (pType2)
  254.                         // obj1 has NO type, but obj2 does
  255.                         return (1);
  256.  
  257.              }
  258.         }
  259.     return (0);
  260. }
  261.  
  262. /*
  263.  *@@ fnCompareClass:
  264.  *      comparison func for sort by object class
  265.  */
  266.  
  267. SHORT EXPENTRY fnCompareClass(PMINIRECORDCORE pmrc1, PMINIRECORDCORE pmrc2, PVOID pStorage)
  268. {
  269.     HAB habDesktop = WinQueryAnchorBlock(HWND_DESKTOP);
  270.     pStorage = pStorage; // to keep the compiler happy
  271.     if ((pmrc1) && (pmrc2))
  272.         if ((pmrc1->pszIcon) && (pmrc2->pszIcon))
  273.         {
  274.             // get SOM objects from cnr record cores
  275.             WPObject *pObj1 = OBJECT_FROM_PREC(pmrc1);
  276.             WPObject *pObj2 = OBJECT_FROM_PREC(pmrc2);
  277.             PSZ psz1, psz2;
  278.             if ((pObj1) && (pObj2))
  279.             {
  280.                 SOMClass *Metaclass = _somGetClass(pObj1);
  281.                 if (Metaclass)
  282.                     psz1 = _wpclsQueryTitle(Metaclass);
  283.                 Metaclass = _somGetClass(pObj2);
  284.                 if (Metaclass)
  285.                     psz2 = _wpclsQueryTitle(Metaclass);
  286.  
  287.                 if ((psz1) && (psz2))
  288.                     switch (WinCompareStrings(habDesktop, 0, 0,
  289.                         psz1, psz2, 0))
  290.                     {
  291.                         case WCS_LT: return (-1);
  292.                         case WCS_GT: return (1);
  293.                     }
  294.              }
  295.         }
  296.     return (0);
  297. }
  298.  
  299. /*
  300.  *@@ fnCompareRealName:
  301.  *      comparison func for sort by real name
  302.  */
  303.  
  304. SHORT EXPENTRY fnCompareRealName(PMINIRECORDCORE pmrc1, PMINIRECORDCORE pmrc2, PVOID pStorage)
  305. {
  306.     HAB habDesktop = WinQueryAnchorBlock(HWND_DESKTOP);
  307.     pStorage = pStorage; // to keep the compiler happy
  308.     if ((pmrc1) && (pmrc2))
  309.         if ((pmrc1->pszIcon) && (pmrc2->pszIcon))
  310.         {
  311.             // get SOM objects from cnr record cores
  312.             WPObject *pObj1 = OBJECT_FROM_PREC(pmrc1);
  313.             WPObject *pObj2 = OBJECT_FROM_PREC(pmrc2);
  314.  
  315.             // the following defaults sort objects last that
  316.             // have no real name (non-file-system objects)
  317.             CHAR sz1[CCHMAXPATH] = {'\255', '\0'},
  318.                  sz2[CCHMAXPATH] = {'\255', '\0'};
  319.  
  320.             if ((pObj1) && (pObj2))
  321.             {
  322.                 if (_somIsA(pObj1, _WPFileSystem))
  323.                     _wpQueryFilename(pObj1, sz1, FALSE);
  324.                 if (_somIsA(pObj2, _WPFileSystem))
  325.                     _wpQueryFilename(pObj2, sz2, FALSE);
  326.  
  327.                 switch (WinCompareStrings(habDesktop, 0, 0,
  328.                     sz1, sz2, 0))
  329.                 {
  330.                     case WCS_LT: return (-1);
  331.                     case WCS_GT: return (1);
  332.                 }
  333.              }
  334.         }
  335.     return (0);
  336. }
  337.  
  338. /*
  339.  *@@ fnCompareSize:
  340.  *      comparison func for sort by size
  341.  */
  342.  
  343. SHORT EXPENTRY fnCompareSize(PMINIRECORDCORE pmrc1, PMINIRECORDCORE pmrc2, PVOID pStorage)
  344. {
  345.     pStorage = pStorage; // to keep the compiler happy
  346.     if ((pmrc1) && (pmrc2))
  347.     {
  348.         // get SOM objects from cnr record cores
  349.         WPObject *pObj1 = OBJECT_FROM_PREC(pmrc1);
  350.         WPObject *pObj2 = OBJECT_FROM_PREC(pmrc2);
  351.         ULONG ul1 = 0, ul2 = 0;
  352.         if ((pObj1) && (pObj2))
  353.         {
  354.             if (_somIsA(pObj1, _WPFileSystem))
  355.                 ul1 = _wpQueryFileSize(pObj1);
  356.             if (_somIsA(pObj2, _WPFileSystem))
  357.                 ul2 = _wpQueryFileSize(pObj2);
  358.  
  359.             if (ul1 < ul2)
  360.                 return (1);
  361.             else if (ul1 > ul2)
  362.                 return (-1);
  363.          }
  364.     }
  365.     return (0);
  366. }
  367.  
  368. /*
  369.  *@@ fnCompareCommonDate:
  370.  *      common comparison func for sort by date functions below;
  371.  *      ulWhat must be:
  372.  *      --  1: compare write date
  373.  *      --  2: compare access date
  374.  *      --  3: compare creation date
  375.  *
  376.  *      This gets called by fnCompareLastWriteDate,
  377.  *      fnCompareLastAccessDate, and fnCompareCreationDate
  378.  *      and should not be specified as a sort function.
  379.  */
  380.  
  381. SHORT EXPENTRY fnCompareCommonDate(PMINIRECORDCORE pmrc1, PMINIRECORDCORE pmrc2,
  382.             ULONG ulWhat)
  383. {
  384.     HAB habDesktop = WinQueryAnchorBlock(HWND_DESKTOP);
  385.     if ((pmrc1) && (pmrc2))
  386.     {
  387.         // get SOM objects from cnr record cores
  388.         WPObject *pObj1 = OBJECT_FROM_PREC(pmrc1);
  389.         WPObject *pObj2 = OBJECT_FROM_PREC(pmrc2);
  390.         CHAR sz1[30] = "9999.99.99 99:99:99",
  391.              sz2[30] = "9999.99.99 99:99:99";
  392.         FDATE fdate;
  393.         FTIME ftime;
  394.         if ((pObj1) && (pObj2))
  395.         {
  396.             if (_somIsA(pObj1, _WPFileSystem))
  397.             {
  398.                 switch (ulWhat) {
  399.                     case 1: _wpQueryLastWrite(pObj1, &fdate, &ftime); break;
  400.                     case 2: _wpQueryLastAccess(pObj1, &fdate, &ftime); break;
  401.                     case 3: _wpQueryCreation(pObj1, &fdate, &ftime); break;
  402.                 }
  403.  
  404.                 sprintf(sz1, "%04d.%02d.%02d %02d:%02d:%02d",
  405.                         ((fdate.year)+1980),
  406.                         fdate.month,
  407.                         fdate.day,
  408.                         ftime.hours,
  409.                         ftime.minutes,
  410.                         (ftime.twosecs * 2));
  411.             }
  412.  
  413.             if (_somIsA(pObj2, _WPFileSystem))
  414.             {
  415.                 switch (ulWhat) {
  416.                     case 1: _wpQueryLastWrite(pObj2, &fdate, &ftime); break;
  417.                     case 2: _wpQueryLastAccess(pObj2, &fdate, &ftime); break;
  418.                     case 3: _wpQueryCreation(pObj2, &fdate, &ftime); break;
  419.                 }
  420.  
  421.                 sprintf(sz2, "%04d.%02d.%02d %02d:%02d:%02d",
  422.                         ((fdate.year)+1980),
  423.                         fdate.month,
  424.                         fdate.day,
  425.                         ftime.hours,
  426.                         ftime.minutes,
  427.                         (ftime.twosecs * 2));
  428.             }
  429.  
  430.             // printf("%s -- %s\n", sz1, sz2);
  431.             switch (WinCompareStrings(habDesktop, 0, 0,
  432.                 sz1, sz2, 0))
  433.             {
  434.                 case WCS_LT: return (-1);
  435.                 case WCS_GT: return (1);
  436.             }
  437.         }
  438.     }
  439.     return (0);
  440. }
  441.  
  442. /*
  443.  *@@ fnCompareLastWriteDate:
  444.  *      comparison func for sort by write date.
  445.  *      This calls fnCompareCommonDate.
  446.  */
  447.  
  448. SHORT EXPENTRY fnCompareLastWriteDate(PMINIRECORDCORE pmrc1, PMINIRECORDCORE pmrc2, PVOID pStorage)
  449. {
  450.     pStorage = pStorage;
  451.     return (fnCompareCommonDate(pmrc1, pmrc2, 1));
  452. }
  453.  
  454. /*
  455.  *@@ fnCompareLastAccessDate:
  456.  *      comparison func for sort by last access date.
  457.  *      This calls fnCompareCommonDate.
  458.  */
  459.  
  460. SHORT EXPENTRY fnCompareLastAccessDate(PMINIRECORDCORE pmrc1, PMINIRECORDCORE pmrc2, PVOID pStorage)
  461. {
  462.     pStorage = pStorage;
  463.     return (fnCompareCommonDate(pmrc1, pmrc2, 2));
  464. }
  465.  
  466. /*
  467.  *@@ fnCompareCreationDate:
  468.  *      comparison func for sort by creation date.
  469.  *      This calls fnCompareCommonDate.
  470.  */
  471.  
  472. SHORT EXPENTRY fnCompareCreationDate(PMINIRECORDCORE pmrc1, PMINIRECORDCORE pmrc2, PVOID pStorage)
  473. {
  474.     pStorage = pStorage;
  475.     return (fnCompareCommonDate(pmrc1, pmrc2, 3));
  476. }
  477.  
  478.  
  479.