home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: WPS_PM / WPS_PM.zip / xfld085s.zip / main / statbars.c < prev    next >
C/C++ Source or Header  |  1999-03-02  |  42KB  |  1,135 lines

  1.  
  2. /*
  3.  *@@sourcefile statbars.c:
  4.  *      this file contains the status bar info translation logic.
  5.  *      It does not contain the status bar's window proc (fnwpStatusBar),
  6.  *      which is in xfldr.c.
  7.  *
  8.  *      All functions in this file are prefixed with "stb*".
  9.  *
  10.  *      This file is new with XFolder 0.81. V0.80 used
  11.  *      SOM multiple inheritance to introduce new methods
  12.  *      with XFldObject, which proved to cause too many problems.
  13.  *      This is now all done in this file using SOM kernel functions
  14.  *      to determine the class of a selected object.
  15.  *
  16.  *      It is thus now much easier to add support for new classes
  17.  *      also, because no new class replacements have to be introduced.
  18.  *      In order to do so, go through all the funcs below and add new
  19.  *      "if" statements. No changes in other files should be necessary.
  20.  *      You will have to add a #include below for that class though
  21.  *      to be able to access the SOM class object for that new class.
  22.  *
  23.  *@@include #define INCL_WINWINDOWMGR
  24.  *@@include #define INCL_DOSMODULEMGR
  25.  *@@include #include <os2.h>
  26.  *@@include #include "xfldr.h"  // for common.h
  27.  *@@include #include "common.h"
  28.  *@@include #include "statbars.h"
  29.  */
  30.  
  31. /*
  32.  *      Copyright (C) 1997-99 Ulrich Möller.
  33.  *      This file is part of the XFolder source package.
  34.  *      XFolder is free software; you can redistribute it and/or modify
  35.  *      it under the terms of the GNU General Public License as published
  36.  *      by the Free Software Foundation, in version 2 as it comes in the
  37.  *      "COPYING" file of the XFolder main distribution.
  38.  *      This program is distributed in the hope that it will be useful,
  39.  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  40.  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  41.  *      GNU General Public License for more details.
  42.  */
  43.  
  44. /*
  45.  *  Suggested #include order:
  46.  *  1)  os2.h
  47.  *  2)  C library headers
  48.  *  3)  SOM headers which work with precompiled header files
  49.  *  4)  headers in /helpers
  50.  *  5)  headers in /main with dlgids.h and common.h first
  51.  *  6)  #pragma hdrstop to prevent VAC++ crashes
  52.  *  7)  other needed SOM headers
  53.  *  8)  for non-SOM-class files: corresponding header (e.g. classlst.h)
  54.  */
  55.  
  56. #define INCL_DOSEXCEPTIONS      // needed for except.h
  57. #define INCL_DOSERRORS
  58.  
  59. #define INCL_WINSHELLDATA       // profile funcs
  60. #define INCL_WINPROGRAMLIST     // needed for WPProgram
  61. #define INCL_WINSTDCNR          // needed for winh.h
  62. #include <os2.h>
  63.  
  64. // C library headers
  65. #include <stdio.h>              // needed for except.h
  66. #include <setjmp.h>             // needed for except.h
  67. #include <assert.h>             // needed for except.h
  68.  
  69. // headers in /helpers
  70. #include "dosh.h"               // Control Program helper routines
  71. #include "winh.h"               // PM helper routines
  72.  
  73. #include "stringh.h"            // string helper routines
  74.  
  75. // SOM headers which don't crash with prec. header files
  76. #include "xfldr.h"
  77. #include "xfobj.h"
  78. #include "xfdisk.h"
  79.  
  80. // headers in /main
  81. #include "dlgids.h"             // all the IDs that are shared with NLS
  82. #include "common.h"             // the majestic XFolder include file
  83.  
  84. #include "except.h"             // XFolder exception handling
  85.  
  86. // other SOM headers
  87. #pragma hdrstop                 // VAC++ keeps crashing otherwise
  88. #include <wppgm.h>              // WPProgram
  89.  
  90. #include "xwps.h"               // XFolder pseudo SOM functions
  91.  
  92. // finally, our own header file
  93. #include "statbars.h"           // status bar translation logic
  94.  
  95. // global variables for storing
  96. CHAR    szXFldObjectStatusBarMnemonics[CCHMAXMNEMONICS] = "";
  97. CHAR    szWPProgramStatusBarMnemonics[CCHMAXMNEMONICS] = "";
  98. CHAR    szXFldDiskStatusBarMnemonics[CCHMAXMNEMONICS] = "";
  99. CHAR    szWPFileSystemStatusBarMnemonics[CCHMAXMNEMONICS] = "";
  100. CHAR    szWPUrlStatusBarMnemonics[CCHMAXMNEMONICS] = "";
  101.  
  102. // WPUrl class object; to preserve compatibility with Warp 3,
  103. // where this class does not exist, we call the SOM kernel
  104. // explicitly to get the class object.
  105. // The initial value of -1 means that we have not queried
  106. // this class yet. After the first query, this either points
  107. // to the class object or is NULL if the class does not exist.
  108. SOMClass    *_WPUrl = (SOMClass*)-1;
  109.  
  110. /* *******************************************************
  111. *                                                        *
  112. *  funcs which operate on a WPS class                    *
  113. *                                                        *
  114. *********************************************************/
  115.  
  116. /*
  117.  *  The following functions all take a SOM class object as
  118.  *  an argument. Presently, the following class objects may
  119.  *  be passed as a parameter:
  120.  *      _XFldObject     (or any descendant)
  121.  *      _WPProgram      (or any descendant)
  122.  *      _XFldDisk       (or any descendant)
  123.  *      _WPFileSystem   (or any descendant)
  124.  *      _WPUrl          (if installed)
  125.  *
  126.  *  Some SOM tricks: _somDescendedFrom(A, B) performed
  127.  *  on two class objects returns TRUE if B is a descendant
  128.  *  of A.
  129.  */
  130.  
  131. /*
  132.  *@@ stbClassAddsNewMnemonics:
  133.  *      returns TRUE if a class introduces new status bar
  134.  *      mnemonics. Used by the "Status bars" notebook page
  135.  *      in the "Select class" dialog to enable/disable
  136.  *      classes which may be selected to set new status
  137.  *      bar single-object information.
  138.  */
  139.  
  140. BOOL stbClassAddsNewMnemonics(SOMClass *pClassObject)
  141. {
  142.     return (    (pClassObject == _XFldObject)
  143.              || (pClassObject == _WPProgram)
  144.              || (pClassObject == _XFldDisk)
  145.              || (pClassObject == _WPFileSystem)
  146.              || ( (_WPUrl != NULL) && (pClassObject == _WPUrl) )
  147.            );
  148. }
  149.  
  150. /*
  151.  *@@ stbSetClassMnemonics:
  152.  *      this changes the status bar mnemonics for "single object"
  153.  *      info for objects of this class and subclasses to
  154.  *      pszText. If *pszText points to null-length string, no
  155.  *      status bar info will be displayed; if pszText is NULL,
  156.  *      the menmonics will be reset to the default value.
  157.  *      This is called by the "Status bars" notebook page
  158.  *      only when the user changes status bar mnemonics.
  159.  */
  160.  
  161. ULONG stbSetClassMnemonics(SOMClass *pClassObject,
  162.                                       PSZ pszText)
  163. {
  164.     if (_WPUrl == (SOMClass*)-1)
  165.     {
  166.         // WPUrl class object not queried yet: do it now
  167.         somId    somidWPUrl = somIdFromString("WPUrl");
  168.         _WPUrl = _somFindClass(SOMClassMgrObject, somidWPUrl, 0, 0);
  169.         // _WPUrl now either points to the WPUrl class object
  170.         // or is NULL if the class is not installed (Warp 3!).
  171.         // In this case, the object will be treated as a regular
  172.         // file-system object.
  173.     }
  174.  
  175.     if (_WPUrl) {
  176.         if (_somDescendedFrom(pClassObject, _WPUrl))
  177.         {
  178.             // provoke a reload of the settings
  179.             // in stbQueryClassMnemonics
  180.             szWPUrlStatusBarMnemonics[0] = '\0';
  181.  
  182.             // set the class mnemonics in OS2.INI; if
  183.             // pszText == NULL, the key will be deleted,
  184.             // and stbQueryClassMnemonics will use
  185.             // the default value
  186.             return (ULONG)PrfWriteProfileString(HINI_USERPROFILE,
  187.                     INIAPP_XFOLDER, INIKEY_SBTEXT_WPURL,
  188.                     pszText);
  189.         }
  190.     }
  191.  
  192.     // no WPUrl or WPUrl not installed: continue
  193.     if (_somDescendedFrom(pClassObject, _WPFileSystem))
  194.     {
  195.         // provoke a reload of the settings
  196.         // in stbQueryClassMnemonics
  197.         szWPFileSystemStatusBarMnemonics[0] = '\0';
  198.  
  199.         // set the class mnemonics in OS2.INI; if
  200.         // pszText == NULL, the key will be deleted,
  201.         // and stbQueryClassMnemonics will use
  202.         // the default value
  203.         return (ULONG)PrfWriteProfileString(HINI_USERPROFILE,
  204.                 INIAPP_XFOLDER, INIKEY_SBTEXT_WPFILESYSTEM,
  205.                 pszText);
  206.     }
  207.     else if (_somDescendedFrom(pClassObject, _XFldDisk))
  208.     {
  209.         // provoke a reload of the settings
  210.         // in stbQueryClassMnemonics
  211.         szXFldDiskStatusBarMnemonics[0] = '\0';
  212.  
  213.         // set the class mnemonics in OS2.INI; if
  214.         // pszText == NULL, the key will be deleted,
  215.         // and stbQueryClassMnemonics will use
  216.         // the default value
  217.         return (ULONG)PrfWriteProfileString(HINI_USERPROFILE,
  218.                 INIAPP_XFOLDER, INIKEY_SBTEXT_WPDISK,
  219.                 pszText);
  220.     }
  221.     else if (pClassObject == _WPProgram)
  222.     {
  223.         // provoke a reload of the settings
  224.         // in stbQueryClassMnemonics
  225.         szWPProgramStatusBarMnemonics[0] = '\0';
  226.  
  227.         // set the class mnemonics in OS2.INI; if
  228.         // pszText == NULL, the key will be deleted,
  229.         // and stbQueryClassMnemonics will use
  230.         // the default value
  231.         return (ULONG)PrfWriteProfileString(HINI_USERPROFILE,
  232.                 INIAPP_XFOLDER, INIKEY_SBTEXT_WPPROGRAM,
  233.                 pszText);
  234.     }
  235.     else if (_somDescendedFrom(pClassObject, _XFldObject))
  236.     {
  237.         // provoke a reload of the settings
  238.         // in stbQueryClassMnemonics
  239.         szXFldObjectStatusBarMnemonics[0] = '\0';
  240.  
  241.         // set the class mnemonics in OS2.INI; if
  242.         // pszText == NULL, the key will be deleted,
  243.         // and stbQueryClassMnemonics will use
  244.         // the default value
  245.         return ((ULONG)PrfWriteProfileString(HINI_USERPROFILE,
  246.                 INIAPP_XFOLDER, INIKEY_SBTEXT_WPOBJECT,
  247.                 pszText));
  248.     }
  249.     return (0);
  250. }
  251.  
  252. /*
  253.  *@@ stbQueryClassMnemonics:
  254.  *      this returns the status bar mnemonics for "single object"
  255.  *      info for objects of pClassObject and subclasses. This string
  256.  *      is either what has been specified on the "Status bar"
  257.  *      notebook page or a default string from the XFolder NLS DLL.
  258.  *      This is called every time the status bar needs to be updated
  259.  *      (stbComposeText) and by the "Status bars" notebook page.
  260.  */
  261.  
  262. ULONG stbQueryClassMnemonics(SOMClass *pClassObject,    // in: class object of selected object
  263.                                       PSZ pszText,      // out: text buffer
  264.                                       ULONG cbText)     // in: sizeof(*pszText)
  265. {
  266.     if (_WPUrl == (SOMClass*)-1)
  267.     {
  268.         // WPUrl class object not queried yet: do it now
  269.         somId    somidWPUrl = somIdFromString("WPUrl");
  270.         _WPUrl = _somFindClass(SOMClassMgrObject, somidWPUrl, 0, 0);
  271.         // _WPUrl now either points to the WPUrl class object
  272.         // or is NULL if the class is not installed (Warp 3!).
  273.     }
  274.  
  275.     if (_WPUrl)
  276.         if (_somDescendedFrom(pClassObject, _WPUrl))
  277.         {
  278.             if (szWPUrlStatusBarMnemonics[0] == '\0')
  279.                 // load string if this is the first time
  280.                 if (PrfQueryProfileString(HINI_USERPROFILE,
  281.                             INIAPP_XFOLDER, INIKEY_SBTEXT_WPURL,
  282.                             NULL, &(szWPUrlStatusBarMnemonics),
  283.                             sizeof(szWPUrlStatusBarMnemonics))
  284.                         == 0)
  285.                     // string not found in profile: set default
  286.                     strcpy(szWPUrlStatusBarMnemonics, "\"$U\"$x(70%)$D $T");
  287.  
  288.             strncpy(pszText, szWPUrlStatusBarMnemonics, cbText);
  289.             pszText[cbText-1] = '\0';
  290.             // get out of here
  291.             return (cbText);
  292.         }
  293.  
  294.     if (_somDescendedFrom(pClassObject, _WPFileSystem))
  295.     {
  296.         if (szWPFileSystemStatusBarMnemonics[0] == '\0')
  297.             // load string if this is the first time
  298.             if (PrfQueryProfileString(HINI_USERPROFILE,
  299.                         INIAPP_XFOLDER, INIKEY_SBTEXT_WPFILESYSTEM,
  300.                         NULL, &(szWPFileSystemStatusBarMnemonics),
  301.                         sizeof(szWPFileSystemStatusBarMnemonics))
  302.                     == 0)
  303.                 // string not found in profile: load default from NLS resources
  304.                 WinLoadString(WinQueryAnchorBlock(HWND_DESKTOP), NLS_MODULE,
  305.                             ID_XSSI_SBTEXTWPDATAFILE,
  306.                             sizeof(szWPFileSystemStatusBarMnemonics),
  307.                             szWPFileSystemStatusBarMnemonics);
  308.  
  309.         strncpy(pszText, szWPFileSystemStatusBarMnemonics, cbText);
  310.         pszText[cbText-1] = '\0';
  311.     }
  312.     //
  313.     else if (_somDescendedFrom(pClassObject, _XFldDisk))
  314.     {
  315.         if (szXFldDiskStatusBarMnemonics[0] == '\0')
  316.             // load string if this is the first time
  317.             if (PrfQueryProfileString(HINI_USERPROFILE,
  318.                         INIAPP_XFOLDER, INIKEY_SBTEXT_WPDISK,
  319.                         NULL, &(szXFldDiskStatusBarMnemonics), sizeof(szXFldDiskStatusBarMnemonics))
  320.                     == 0)
  321.                 // string not found in profile: load default from NLS resources
  322.                 WinLoadString(WinQueryAnchorBlock(HWND_DESKTOP), NLS_MODULE,
  323.                             ID_XSSI_SBTEXTWPDISK,
  324.                             sizeof(szXFldDiskStatusBarMnemonics),
  325.                             szXFldDiskStatusBarMnemonics);
  326.  
  327.         strncpy(pszText, szXFldDiskStatusBarMnemonics, cbText);
  328.         pszText[cbText-1] = '\0';
  329.     }
  330.     //
  331.     else if (_somDescendedFrom(pClassObject, _WPProgram))
  332.     {
  333.         if (szWPProgramStatusBarMnemonics[0] == '\0')
  334.             // load string if this is the first time
  335.             if (PrfQueryProfileString(HINI_USERPROFILE,
  336.                         INIAPP_XFOLDER, INIKEY_SBTEXT_WPPROGRAM,
  337.                         NULL, &(szWPProgramStatusBarMnemonics), sizeof(szWPProgramStatusBarMnemonics))
  338.                     == 0)
  339.                 // string not found in profile: load default from NLS resources
  340.                 WinLoadString(WinQueryAnchorBlock(HWND_DESKTOP), NLS_MODULE,
  341.                             ID_XSSI_SBTEXTWPPROGRAM,
  342.                             sizeof(szWPProgramStatusBarMnemonics),
  343.                             szWPProgramStatusBarMnemonics);
  344.  
  345.         strncpy(pszText, szWPProgramStatusBarMnemonics, cbText);
  346.         pszText[cbText-1] = '\0';
  347.     }
  348.     // subsidiarily: XFldObject
  349.     else if (_somDescendedFrom(pClassObject, _XFldObject))
  350.     {
  351.         // should always be TRUE
  352.         if (szXFldObjectStatusBarMnemonics[0] == '\0')
  353.             // load string if this is the first time
  354.             if (PrfQueryProfileString(HINI_USERPROFILE,
  355.                         INIAPP_XFOLDER, INIKEY_SBTEXT_WPOBJECT,
  356.                         NULL, &(szXFldObjectStatusBarMnemonics),
  357.                                 sizeof(szXFldObjectStatusBarMnemonics))
  358.                     == 0)
  359.                 // string not found in profile: load default from NLS resources
  360.                 WinLoadString(WinQueryAnchorBlock(HWND_DESKTOP), NLS_MODULE,
  361.                             ID_XSSI_SBTEXTWPOBJECT,
  362.                             sizeof(szXFldObjectStatusBarMnemonics),
  363.                             szXFldObjectStatusBarMnemonics);
  364.  
  365.         strncpy(pszText, szXFldObjectStatusBarMnemonics, cbText);
  366.         pszText[cbText-1] = '\0';
  367.     } else
  368.         strcpy(pszText, "???");     // should not occur
  369.     return (cbText);
  370. }
  371.  
  372. /* *******************************************************
  373. *                                                        *
  374. *  funcs which operate on a WPS object                   *
  375. *                                                        *
  376. *********************************************************/
  377.  
  378. /*
  379.  *@@ stbTranslateSingleMnemonics:
  380.  *      this method is called on an object by stbComposeText
  381.  *      after the status bar mnemonics have been queried
  382.  *      for the object's class using stbQueryClassMnemonics,
  383.  *      which is passed to this function in pszText.
  384.  *      As opposed to the functions above, this does not
  385.  *      take a class object, but an _instance_ as a parameter,
  386.  *      because the info has to be displayed for each object
  387.  *      differently.
  388.  *      Note that stbComposeText has changed all the '$' characters
  389.  *      in pszText to the tabulator char ('\t') to avoid
  390.  *      unwanted results if text inserted during the translations
  391.  *      contains '$' chars. So we search for '\t' keys in this
  392.  *      function.
  393.  *      This returns the number of keys that were translated.
  394.  */
  395.  
  396. ULONG  stbTranslateSingleMnemonics(SOMClass *pObject,
  397.                                       PSZ pszText,      // in/out: status bar text
  398.                                       ULONG cbText,     // in: size of *pszText
  399.                                       CHAR cThousands)  // in: thousands separator
  400. {
  401.     ULONG       ulrc = 0;
  402.     CHAR        szTemp[300];
  403.     PSZ         p;
  404.  
  405.     /*
  406.      * WPUrl:
  407.      *
  408.      */
  409.  
  410.     /* first check if the thing is a URL object;
  411.        in addition to the normal WPFileSystem mnemonics,
  412.        URL objects also support the $U mnemonic for
  413.        displaying the URL */
  414.  
  415.     if (_WPUrl == (SOMClass*)-1)
  416.     {
  417.         // WPUrl class object not queried yet: do it now
  418.         somId    somidWPUrl = somIdFromString("WPUrl");
  419.         _WPUrl = _somFindClass(SOMClassMgrObject, somidWPUrl, 0, 0);
  420.         // _WPUrl now either points to the WPUrl class object
  421.         // or is NULL if the class is not installed (Warp 3!).
  422.     }
  423.  
  424.     if (_WPUrl)
  425.         if (_somIsA(pObject, _WPUrl))
  426.         {
  427.             // yes, we have a URL object:
  428.             if (p = strstr(pszText, "\tU")) // URL mnemonic
  429.             {
  430.                 CHAR szFilename[CCHMAXPATH];
  431.                 PSZ pszFilename = _wpQueryFilename(pObject, szFilename, TRUE);
  432.  
  433.                 // read in the contents of the file, which
  434.                 // contain the URL
  435.                 PSZ pszURL = NULL;
  436.                 if (pszFilename)
  437.                     pszURL = doshReadTextFile(pszFilename, 0);
  438.                     if (pszURL) {
  439.                         if (strlen(pszURL) > 100)
  440.                             strcpy(pszURL+97, "...");
  441.                         strhReplace(pszText, "\tU", pszURL);
  442.                         free(pszURL);
  443.                     }
  444.                 if (!pszURL)
  445.                     strhReplace(pszText, "\tU", "?");
  446.                 ulrc++;
  447.             }
  448.         }
  449.  
  450.     /*
  451.      * WPFileSystem:
  452.      *
  453.      */
  454.  
  455.     if (_somIsA(pObject, _WPFileSystem))
  456.     {
  457.         /* single-object status bar text mnemonics understood by WPFileSystem
  458.            (in addition to those introduced by XFldObject):
  459.  
  460.              $r      object's real name
  461.  
  462.              $y      object type (.TYPE EA)
  463.              $D      object creation date
  464.              $T      object creation time
  465.              $a      object attributes
  466.  
  467.              $Eb     EA size in bytes
  468.              $Ek     EA size in kBytes
  469.              $EK     EA size in KBytes
  470.          */
  471.  
  472.         if (p = strstr(pszText, "\ty")) // attribs
  473.         {
  474.             PSZ p2 = NULL;
  475.             p2 = _wpQueryType(pObject);
  476.             strhReplace(pszText, "\ty", (p2) ? p2 : "?");
  477.             ulrc++;
  478.         }
  479.  
  480.         if (p = strstr(pszText, "\tD"))  // date
  481.         {
  482.             FILEFINDBUF4 ffb4;
  483.             ULONG ulDateFormat =
  484.                 PrfQueryProfileInt(HINI_USER, "PM_National", "iDate", 0);
  485.             CHAR szDateSep[10];
  486.             PrfQueryProfileString(HINI_USER, "PM_National", "sDate", "/",
  487.                 szDateSep, sizeof(szDateSep)-1);
  488.  
  489.             strcpy(szTemp, "?");
  490.             _wpQueryDateInfo(pObject, &ffb4);
  491.             strhFileDate(szTemp, &(ffb4.fdateLastWrite), ulDateFormat, szDateSep[0]);
  492.             strhReplace(pszText, "\tD", szTemp);
  493.             ulrc++;
  494.         }
  495.  
  496.         if (p = strstr(pszText, "\tT"))  // time
  497.         {
  498.             FILEFINDBUF4 ffb4;
  499.             ULONG ulTimeFormat =
  500.                 PrfQueryProfileInt(HINI_USER, "PM_National", "iTime", 0);
  501.             CHAR szTimeSep[10];
  502.             PrfQueryProfileString(HINI_USER, "PM_National", "sTime", ":",
  503.                 szTimeSep, sizeof(szTimeSep)-1);
  504.  
  505.             strcpy(szTemp, "?");
  506.             _wpQueryDateInfo(pObject, &ffb4);
  507.             strhFileTime(szTemp, &(ffb4.ftimeLastWrite), ulTimeFormat, szTimeSep[0]);
  508.             strhReplace(pszText, "\tT", szTemp);
  509.             ulrc++;
  510.         }
  511.  
  512.         if (p = strstr(pszText, "\ta")) // attribs
  513.         {
  514.             ULONG fAttr = _wpQueryAttr(pObject);
  515.             szTemp[0] = (fAttr & FILE_ARCHIVED) ? 'A' : 'a';
  516.             szTemp[1] = (fAttr & FILE_HIDDEN  ) ? 'H' : 'h';
  517.             szTemp[2] = (fAttr & FILE_READONLY) ? 'R' : 'r';
  518.             szTemp[3] = (fAttr & FILE_SYSTEM  ) ? 'S' : 's';
  519.             szTemp[4] = '\0';
  520.             strhReplace(pszText, "\ta", szTemp);
  521.             ulrc++;
  522.         }
  523.  
  524.         if (p = strstr(pszText, "\tEb")) // easize
  525.         {
  526.             ULONG ulEASize;
  527.             ulEASize = _wpQueryEASize(pObject);
  528.             strhThousandsDouble(szTemp, ulEASize, cThousands);
  529.             strhReplace(pszText, "\tEb", szTemp);
  530.             ulrc++;
  531.         }
  532.  
  533.         if (p = strstr(pszText, "\tEk"))
  534.         {
  535.             ULONG ulEASize;
  536.             ulEASize = _wpQueryEASize(pObject);
  537.             strhThousandsDouble(szTemp, ((ulEASize+500)/1000), cThousands);
  538.             strhReplace(pszText, "\tEk", szTemp);
  539.             ulrc++;
  540.         }
  541.  
  542.         if (p = strstr(pszText, "\tEK"))
  543.         {
  544.             ULONG ulEASize;
  545.             ulEASize = _wpQueryEASize(pObject);
  546.             strhThousandsDouble(szTemp, ((ulEASize+512)/1024), cThousands);
  547.             strhReplace(pszText, "\tEK", szTemp);
  548.             ulrc++;
  549.         }
  550.  
  551.         if (p = strstr(pszText, "\tr")) // real name
  552.         {
  553.             strcpy(szTemp, "?");
  554.             _wpQueryFilename(pObject, szTemp, FALSE);
  555.             strhReplace(pszText, "\tr", szTemp);
  556.             ulrc++;
  557.         }
  558.     }
  559.  
  560.     /*
  561.      * XFldDisk:
  562.      *
  563.      */
  564.  
  565.     else if (_somIsA(pObject, _XFldDisk))
  566.     {
  567.         ULONG ulLogicalDrive = -1;
  568.  
  569.         /* single-object status bar text mnemonics understood by XFldDisk:
  570.  
  571.              $F      file system type (HPFS, FAT, CDFS, ...)
  572.  
  573.              $fb     free space on drive in bytes
  574.              $fk     free space on drive in kBytes
  575.              $fK     free space on drive in KBytes
  576.              $fm     free space on drive in mBytes
  577.              $fM     free space on drive in MBytes
  578.  
  579.             NOTE: the $f keys are also handled by stbComposeText, but
  580.                   those only work properly for file-system objects, so we need
  581.                   to calculate these values for these (abstract) disk objects
  582.  
  583.          */
  584.  
  585.         // the following are for free space on drive
  586.         if (p = strstr(pszText, "\tfb"))
  587.         {
  588.             double dbl;
  589.  
  590.             if (ulLogicalDrive == -1) {
  591.                 ulLogicalDrive = _wpQueryLogicalDrive(pObject);
  592.                 if (doshAssertDrive(ulLogicalDrive,
  593.                                                 TRUE)  // prohibit popups
  594.                             != NO_ERROR)
  595.                     ulLogicalDrive = 0;
  596.             }
  597.  
  598.             dbl = doshQueryDiskFree(ulLogicalDrive);
  599.             if (dbl == -1)
  600.                 strcpy(szTemp, "?");
  601.             else
  602.                 strhThousandsDouble(szTemp, dbl,
  603.                     cThousands);
  604.             strhReplace(pszText, "\tfb", szTemp);
  605.             ulrc++;
  606.         }
  607.  
  608.         if (p = strstr(pszText, "\tfk"))
  609.         {
  610.             double dbl;
  611.  
  612.             if (ulLogicalDrive == -1) {
  613.                 ulLogicalDrive = _wpQueryLogicalDrive(pObject);
  614.                 if (doshAssertDrive(ulLogicalDrive,
  615.                                                 TRUE)  // prohibit popups
  616.                             != NO_ERROR)
  617.                     ulLogicalDrive = 0;
  618.             }
  619.  
  620.             dbl = doshQueryDiskFree(ulLogicalDrive);
  621.             if (dbl == -1)
  622.                 strcpy(szTemp, "?");
  623.             else
  624.                 strhThousandsDouble(szTemp,
  625.                     ((dbl + 500) / 1000),
  626.                     cThousands);
  627.             strhReplace(pszText, "\tfk", szTemp);
  628.             ulrc++;
  629.         }
  630.  
  631.         if (p = strstr(pszText, "\tfK"))
  632.         {
  633.             double dbl;
  634.  
  635.             if (ulLogicalDrive == -1) {
  636.                 ulLogicalDrive = _wpQueryLogicalDrive(pObject);
  637.                 if (doshAssertDrive(ulLogicalDrive,
  638.                                                 TRUE)  // prohibit popups
  639.                             != NO_ERROR)
  640.                     ulLogicalDrive = 0;
  641.             }
  642.  
  643.             dbl = doshQueryDiskFree(ulLogicalDrive);
  644.             if (dbl == -1)
  645.                 strcpy(szTemp, "?");
  646.             else
  647.                 strhThousandsDouble(szTemp,
  648.                     ((dbl + 512) / 1024),
  649.                     cThousands);
  650.             strhReplace(pszText, "\tfK", szTemp);
  651.             ulrc++;
  652.         }
  653.  
  654.         if (p = strstr(pszText, "\tfm"))
  655.         {
  656.             double dbl;
  657.  
  658.             if (ulLogicalDrive == -1) {
  659.                 ulLogicalDrive = _wpQueryLogicalDrive(pObject);
  660.                 if (doshAssertDrive(ulLogicalDrive,
  661.                                                 TRUE)  // prohibit popups
  662.                             != NO_ERROR)
  663.                     ulLogicalDrive = 0;
  664.             }
  665.  
  666.             dbl = doshQueryDiskFree(ulLogicalDrive);
  667.             if (dbl == -1)
  668.                 strcpy(szTemp, "?");
  669.             else
  670.                 strhThousandsDouble(szTemp,
  671.                     ((dbl +500000) / 1000000),
  672.                     cThousands);
  673.             strhReplace(pszText, "\tfm", szTemp);
  674.             ulrc++;
  675.         }
  676.  
  677.         if (p = strstr(pszText, "\tfM"))
  678.         {
  679.             double dbl;
  680.  
  681.             if (ulLogicalDrive == -1) {
  682.                 ulLogicalDrive = _wpQueryLogicalDrive(pObject);
  683.                 if (doshAssertDrive(ulLogicalDrive,
  684.                                                 TRUE)  // prohibit popups
  685.                             != NO_ERROR)
  686.                     ulLogicalDrive = 0;
  687.             }
  688.  
  689.             dbl = doshQueryDiskFree(ulLogicalDrive);
  690.             if (dbl == -1)
  691.                 strcpy(szTemp, "?");
  692.             else
  693.                strhThousandsDouble(szTemp,
  694.                     ((dbl + (1024*1024/2)) / (1024*1024)),
  695.                     cThousands);
  696.             strhReplace(pszText, "\tfM", szTemp);
  697.             ulrc++;
  698.         }
  699.  
  700.         if (p = strstr(pszText, "\tF"))  // file-system type (HPFS, ...)
  701.         {
  702.             CHAR szBuffer[200];
  703.  
  704.             if (ulLogicalDrive == -1) {
  705.                 ulLogicalDrive = _wpQueryLogicalDrive(pObject);
  706.                 if (doshAssertDrive(ulLogicalDrive,
  707.                                                 TRUE)  // prohibit popups
  708.                             != NO_ERROR)
  709.                     ulLogicalDrive = 0;
  710.             }
  711.  
  712.             if (doshQueryDiskFSType(ulLogicalDrive, szBuffer) == NO_ERROR)
  713.                 strhReplace(pszText, "\tF", szBuffer);
  714.             else
  715.                 strhReplace(pszText, "\tF", "?");
  716.             ulrc++;
  717.         }
  718.     }
  719.  
  720.     /*
  721.      * WPProgram:
  722.      *
  723.      */
  724.  
  725.     else if (_somIsA(pObject, _WPProgram))
  726.     {
  727.         PPROGDETAILS pProgDetails = NULL;
  728.         ULONG       ulSize;
  729.  
  730.         /* single-object status bar text mnemonics understood by WPFileSystem
  731.            (in addition to those introduced by XFldObject):
  732.  
  733.             $p      executable program file (as specified in the Settings)
  734.             $P      parameter list (as specified in the Settings)
  735.             $d      working directory (as specified in the Settings)
  736.          */
  737.  
  738.         if (p = strstr(pszText, "\tp"))  // program executable
  739.         {
  740.             strcpy(szTemp, "?");
  741.             if (!pProgDetails)
  742.                 if ((_wpQueryProgDetails(pObject, (PPROGDETAILS)NULL, &ulSize)))
  743.                     if ((pProgDetails = (PPROGDETAILS)_wpAllocMem(pObject, ulSize, NULL)) != NULL)
  744.                         _wpQueryProgDetails(pObject, pProgDetails, &ulSize);
  745.  
  746.             if (pProgDetails)
  747.                 if (pProgDetails->pszExecutable)
  748.                     strcpy(szTemp, pProgDetails->pszExecutable);
  749.                 else strcpy(szTemp, "");
  750.  
  751.             strhReplace(pszText, "\tp", szTemp);
  752.             ulrc++;
  753.         }
  754.  
  755.         if (p = strstr(pszText, "\tP"))  // program executable
  756.         {
  757.             strcpy(szTemp, "?");
  758.             if (!pProgDetails)
  759.                 if ((_wpQueryProgDetails(pObject, (PPROGDETAILS)NULL, &ulSize)))
  760.                     if ((pProgDetails = (PPROGDETAILS)_wpAllocMem(pObject, ulSize, NULL)) != NULL)
  761.                         _wpQueryProgDetails(pObject, pProgDetails, &ulSize);
  762.  
  763.             if (pProgDetails)
  764.                 if (pProgDetails->pszParameters)
  765.                     strcpy(szTemp, pProgDetails->pszParameters);
  766.                 else strcpy(szTemp, "");
  767.  
  768.             strhReplace(pszText, "\tP", szTemp);
  769.             ulrc++;
  770.         }
  771.  
  772.         if (p = strstr(pszText, "\td"))  // startup dir
  773.         {
  774.             strcpy(szTemp, "?");
  775.             if (!pProgDetails)
  776.                 if ((_wpQueryProgDetails(pObject, (PPROGDETAILS)NULL, &ulSize)))
  777.                     if ((pProgDetails = (PPROGDETAILS)_wpAllocMem(pObject, ulSize, NULL)) != NULL)
  778.                         _wpQueryProgDetails(pObject, pProgDetails, &ulSize);
  779.  
  780.             if (pProgDetails)
  781.                 if (pProgDetails->pszStartupDir)
  782.                     strcpy(szTemp, pProgDetails->pszStartupDir);
  783.                 else strcpy(szTemp, "");
  784.  
  785.             strhReplace(pszText, "\td", szTemp);
  786.             ulrc++;
  787.         }
  788.  
  789.         if (pProgDetails)
  790.             _wpFreeMem(pObject, (PBYTE)pProgDetails);
  791.     }
  792.  
  793.     /*
  794.      * XFldObject:
  795.      *
  796.      */
  797.  
  798.     if (_somIsA(pObject, _XFldObject))      // should always be TRUE
  799.     {
  800.         CHAR        szTemp[300];
  801.         PSZ         p;
  802.  
  803.         /* single-object status bar text mnemonics understood by XFldObject:
  804.              $t      object title
  805.              $w      WPS class default title (e.g. "Data file")
  806.              $W      WPS class name (e.g. WPDataFile)
  807.          */
  808.  
  809.         if (p = strstr(pszText, "\tw"))     // class default title
  810.         {
  811.             SOMClass *pClassObject = _somGetClass(pObject);
  812.             if (pClassObject)
  813.                 strhReplace(pszText, "\tw", _wpclsQueryTitle(pClassObject));
  814.             else strhReplace(pszText, "\tw", "?");
  815.             ulrc++;
  816.         }
  817.  
  818.         if (p = strstr(pszText, "\tW"))     // class name
  819.         {
  820.             strcpy(szTemp, "?");
  821.             strhReplace(pszText, "\tW", _somGetClassName(pObject));
  822.             ulrc++;
  823.         }
  824.  
  825.         if (p = strstr(pszText, "\tt"))          // object title
  826.         {
  827.             strcpy(szTemp, "?");
  828.             strcpy(szTemp, _wpQueryTitle(pObject));
  829.             strhBeautifyTitle(szTemp);
  830.             strhReplace(pszText, "\tt", szTemp);
  831.             ulrc++;
  832.         }
  833.     }
  834.  
  835.     return (ulrc);
  836. }
  837.  
  838. /*
  839.  *@@ stbComposeText:
  840.  *      this is the main entry point to the status bar
  841.  *      logic which gets called by the status bar wnd
  842.  *      proc (fnwpStatusBar, xfldr.c) when the status
  843.  *      bar text needs updating.
  844.  *         This func first finds out which mode the status
  845.  *      bar should operate in (depending on how many objects
  846.  *      are currently selected in hwndCnr), and then selects
  847.  *      the matching status bar mnemonic string and does the
  848.  *      translation into meaningful information.
  849.  *         If only one object is selected (one-object mode),
  850.  *      stbTranslateSingleMnemonics (above) is called to
  851.  *      do translations for one-object mode.
  852.  *         No-object and many-objects modes are handled
  853.  *      by this func directly, because these only use
  854.  *      the mnemonics which are valid for all modes.
  855.  */
  856.  
  857. BOOL stbComposeText(WPFolder* somSelf,      // in:  open folder with status bar
  858.                     HWND hwndCnr,           // in:  cnr hwnd of that folder's open view
  859.                     PSZ pszText,            // out: text buffer
  860.                     ULONG cbText)           // in:  sizeof(*pszText)
  861. {
  862.    /* Generic status bar mnemonics handled here (for other than
  863.       "single object" mode too):
  864.  
  865.         $c      no. of selected objects
  866.         $C      total object count
  867.  
  868.         $fb     free space on drive in bytes
  869.         $fk     free space on drive in kBytes
  870.         $fK     free space on drive in KBytes
  871.         $fm     free space on drive in mBytes
  872.         $fM     free space on drive in MBytes
  873.  
  874.         $sb     size of selected objects in bytes
  875.         $sk     size of selected objects in kBytes
  876.         $sK     size of selected objects in KBytes
  877.         $sm     size of selected objects in mBytes
  878.         $sM     size of selected objects in MBytes
  879.  
  880.         $Sb     size of folder content in bytes
  881.         $Sk     size of folder content in kBytes
  882.         $SK     size of folder content in KBytes
  883.         $Sm     size of folder content in mBytes
  884.         $SM     size of folder content in MBytes
  885.  
  886.        The "single object" mode mnemonics are translated using
  887.        the above functions afterwards.
  888.     */
  889.  
  890.     BOOL        brc = FALSE;
  891.  
  892.     CNRINFO     CnrInfo;
  893.     PMINIRECORDCORE pmrcSelected, pmrc2;
  894.     ULONG       ulSelectedCount = 0,
  895.                 ulSizeSelected = 0,
  896.                 ulSizeTotal = 0;
  897.     WPObject    *pObject = NULL,
  898.                 *pObject2 = NULL;
  899.  
  900.     CHAR        szThousand[10],
  901.                 szTemp[300];
  902.     PSZ         p;
  903.     CHAR        *p2;
  904.  
  905.     // go thru all the selected objects in the container
  906.     // and sum up the size of the corresponding objects in
  907.     // ulSizeSelected
  908.     pmrcSelected = (PMINIRECORDCORE)CMA_FIRST;
  909.     do {
  910.         pmrcSelected =
  911.             (PMINIRECORDCORE)WinSendMsg(hwndCnr,
  912.                     CM_QUERYRECORDEMPHASIS,
  913.                     (MPARAM)pmrcSelected,       // CMA_FIRST at first loop
  914.                     (MPARAM)CRA_SELECTED);
  915.         if (pmrcSelected) {
  916.             ulSelectedCount++;
  917.             pObject = OBJECT_FROM_PREC(pmrcSelected);
  918.             if (pObject)
  919.                 if (xwpsCheckObject(pObject)) {
  920.                     if (_somIsA(pObject, _WPFileSystem))
  921.                         ulSizeSelected += _wpQueryFileSize(pObject);
  922.                 } else pObject = NULL;
  923.         }
  924.     } while (pmrcSelected);
  925.  
  926.     // get thousands separator from "Country" object
  927.     PrfQueryProfileString(HINI_USER, "PM_Default_National", "sThousand",
  928.             ",", szThousand, sizeof(szThousand)-1);
  929.  
  930.     // now get the mnemonics which have been set by the
  931.     // user on the "Status bar" page, depending on how many
  932.     // objects are selected
  933.     if ( (ulSelectedCount == 0) || (pObject == NULL) )
  934.         // "no object" mode
  935.         strcpy(pszText,
  936.                 cmnQueryStatusBarSetting(SBS_TEXTNONESEL));
  937.     else if (ulSelectedCount == 1) {
  938.         // "single-object" mode: query the text to translate
  939.         // from the object, because we can implement
  940.         // different mnemonics for different WPS classes
  941.         stbQueryClassMnemonics(
  942.                 _somGetClass(pObject), // object's class object
  943.                 pszText, cbText);
  944.     } else
  945.         // "multiple objects" mode
  946.         strcpy(pszText,
  947.                 cmnQueryStatusBarSetting(SBS_TEXTMULTISEL));
  948.  
  949.     // before actually translating any "$" keys, all the
  950.     // '$' characters in the mnemonic string are changed to
  951.     // the tabulator character ('\t') to avoid having '$'
  952.     // characters translated which might only have been
  953.     // inserted during the translation, e.g. because a
  954.     // filename contains a '$' character.
  955.     // All the translation logic will then only search for
  956.     // those tab characters.
  957.     while (p2 = strchr(pszText, '$'))
  958.         *p2 = '\t';
  959.  
  960.     if (ulSelectedCount == 1)
  961.         // "single-object" mode: translate
  962.         // object-specific mnemonics first
  963.         stbTranslateSingleMnemonics(
  964.                 pObject,               // the object itself
  965.                 pszText, cbText,
  966.                 szThousand[0]);
  967.  
  968.     // query total object count (CnrInfo.cRecords)
  969.     winhQueryCnrInfo(hwndCnr, CnrInfo);
  970.  
  971.     // if we have a "total size" query, also sum up the size of
  972.     // the whole folder into ulSizeTotal, which will be handled
  973.     // in detail below
  974.     if (strstr(pszText, "\tS"))
  975.     {
  976.         #ifdef DEBUG_STATUSBARS
  977.             _Pmpf(("Calculating total size"));
  978.         #endif
  979.         pmrc2 = NULL;
  980.         do {
  981.             pmrc2 =
  982.                 (PMINIRECORDCORE)WinSendMsg(hwndCnr,
  983.                         CM_QUERYRECORD,
  984.                         (MPARAM)pmrc2,
  985.                         MPFROM2SHORT(
  986.                             (pmrc2)
  987.                                     ? CMA_NEXT
  988.                                     : CMA_FIRST,    // for first loop
  989.                             CMA_ITEMORDER)          // doesn't matter
  990.                         );
  991.             if (pmrc2) {
  992.                 pObject2 = OBJECT_FROM_PREC(pmrc2);
  993.                 if (pObject2)
  994.                     if (xwpsCheckObject(pObject2)) {
  995.                         if (_somIsA(pObject2, _WPFileSystem)) {
  996.                             ulSizeTotal += _wpQueryFileSize(pObject2);
  997.                         }
  998.                     }
  999.             }
  1000.         } while (pmrc2);
  1001.  
  1002.         #ifdef DEBUG_STATUSBARS
  1003.             _Pmpf(("  Result: %d", ulSizeTotal));
  1004.         #endif
  1005.     }
  1006.  
  1007.     if (p = strstr(pszText, "\tc")) // selected objs count
  1008.     {
  1009.         sprintf(szTemp, "%d", ulSelectedCount);
  1010.         strhReplace(pszText, "\tc", szTemp);
  1011.     }
  1012.  
  1013.     if (p = strstr(pszText, "\tC")) // total obj count
  1014.     {
  1015.         sprintf(szTemp, "%d", CnrInfo.cRecords);
  1016.         strhReplace(pszText, "\tC", szTemp);
  1017.     }
  1018.  
  1019.     // the following are for free space on drive
  1020.  
  1021.     if (p = strstr(pszText, "\tfb"))
  1022.     {
  1023.         strhThousandsDouble(szTemp,
  1024.                 xwpsQueryDiskFreeFromFolder(somSelf),
  1025.                 szThousand[0]);
  1026.         strhReplace(pszText, "\tfb", szTemp);
  1027.     }
  1028.  
  1029.     if (p = strstr(pszText, "\tfk"))
  1030.     {
  1031.         strhThousandsDouble(szTemp,
  1032.                 ((xwpsQueryDiskFreeFromFolder(somSelf) + 500) / 1000),
  1033.                 szThousand[0]);
  1034.         strhReplace(pszText, "\tfk", szTemp);
  1035.     }
  1036.  
  1037.     if (p = strstr(pszText, "\tfK"))
  1038.     {
  1039.         strhThousandsDouble(szTemp,
  1040.                 ((xwpsQueryDiskFreeFromFolder(somSelf) + 512) / 1024),
  1041.                 szThousand[0]);
  1042.         strhReplace(pszText, "\tfK", szTemp);
  1043.     }
  1044.  
  1045.     if (p = strstr(pszText, "\tfm"))
  1046.     {
  1047.         strhThousandsDouble(szTemp,
  1048.                 ((xwpsQueryDiskFreeFromFolder(somSelf) +500000) / 1000000),
  1049.                 szThousand[0]);
  1050.         strhReplace(pszText, "\tfm", szTemp);
  1051.     }
  1052.  
  1053.     if (p = strstr(pszText, "\tfM"))
  1054.     {
  1055.         strhThousandsDouble(szTemp,
  1056.                 ((xwpsQueryDiskFreeFromFolder(somSelf) + (1024*1024/2)) / (1024*1024)),
  1057.                 szThousand[0]);
  1058.         strhReplace(pszText, "\tfM", szTemp);
  1059.     }
  1060.  
  1061.     // the following are for SELECTED size
  1062.     if (p = strstr(pszText, "\tsb"))
  1063.     {
  1064.         strhThousandsULong(szTemp, ulSizeSelected, szThousand[0]);
  1065.         strhReplace(pszText, "\tsb", szTemp);
  1066.     }
  1067.  
  1068.     if (p = strstr(pszText, "\tsk"))
  1069.     {
  1070.         strhThousandsULong(szTemp, ((ulSizeSelected+500) / 1000), szThousand[0]);
  1071.         strhReplace(pszText, "\tsk", szTemp);
  1072.     }
  1073.  
  1074.     if (p = strstr(pszText, "\tsK"))
  1075.     {
  1076.         strhThousandsULong(szTemp, ((ulSizeSelected+512) / 1024), szThousand[0]);
  1077.         strhReplace(pszText, "\tsK", szTemp);
  1078.     }
  1079.  
  1080.     if (p = strstr(pszText, "\tsm"))
  1081.     {
  1082.         strhThousandsULong(szTemp, ((ulSizeSelected+500000) / 1000000), szThousand[0]);
  1083.         strhReplace(pszText, "\tsm", szTemp);
  1084.     }
  1085.  
  1086.     if (p = strstr(pszText, "\tsM"))
  1087.     {
  1088.         strhThousandsULong(szTemp, ((ulSizeSelected+(1024*1024/2)) / (1024*1024)), szThousand[0]);
  1089.         strhReplace(pszText, "\tsM", szTemp);
  1090.     }
  1091.  
  1092.     // the following are for TOTAL folder size
  1093.     if (p = strstr(pszText, "\tSb"))
  1094.     {
  1095.         strhThousandsULong(szTemp, ulSizeTotal, szThousand[0]);
  1096.         strhReplace(pszText, "\tSb", szTemp);
  1097.     }
  1098.  
  1099.     if (p = strstr(pszText, "\tSk"))
  1100.     {
  1101.         strhThousandsULong(szTemp, ((ulSizeTotal+500) / 1000), szThousand[0]);
  1102.         strhReplace(pszText, "\tSk", szTemp);
  1103.     }
  1104.  
  1105.     if (p = strstr(pszText, "\tSK"))
  1106.     {
  1107.         strhThousandsULong(szTemp, ((ulSizeTotal+512) / 1024), szThousand[0]);
  1108.         strhReplace(pszText, "\tSK", szTemp);
  1109.     }
  1110.  
  1111.     if (p = strstr(pszText, "\tSm"))
  1112.     {
  1113.         strhThousandsULong(szTemp, ((ulSizeTotal+500000) / 1000000), szThousand[0]);
  1114.         strhReplace(pszText, "\tSm", szTemp);
  1115.     }
  1116.  
  1117.     if (p = strstr(pszText, "\tSM"))
  1118.     {
  1119.         strhThousandsULong(szTemp, ((ulSizeTotal+(1024*1024/2)) / (1024*1024)), szThousand[0]);
  1120.         strhReplace(pszText, "\tSM", szTemp);
  1121.     }
  1122.  
  1123.     // now translate remaining '\t' characters back into
  1124.     // '$' characters; this might happen if the user actually
  1125.     // wanted to see a '$' character displayed
  1126.     while (p2 = strchr(pszText, '\t'))
  1127.         *p2 = '$';
  1128.  
  1129.     brc = TRUE;
  1130.  
  1131.     return (brc);
  1132. }
  1133.  
  1134.  
  1135.