home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: SysTools / SysTools.zip / sysba021.zip / SRC.ZIP / sysbar2 / Piper / sb2_pipe.cpp < prev    next >
C/C++ Source or Header  |  2003-01-03  |  147KB  |  4,270 lines

  1. /*
  2.  
  3.   SysBar/2 Utility Set  version 0.21
  4.  
  5.   Pipe Monitor module
  6.  
  7.   ..................................................................
  8.  
  9.   Copyright (c) 1995-99  Dmitry I. Platonoff <dip@platonoff.com>
  10.   Copyright (c) 2002,03  Max Alekseyev       <relf@os2.ru>
  11.  
  12.                          All rights reserved
  13.  
  14.   ..................................................................
  15.  
  16.   LICENSE
  17.   ~~~~~~~
  18.   Redistribution and use in source and binary forms, with or without
  19.   modification, are permitted provided that the following conditions
  20.   are met:
  21.  
  22.   1. Redistributions of source code must retain the above copyright
  23.      notice, this list of conditions and the following disclaimer.
  24.  
  25.   2. Redistributions in binary form must reproduce the above
  26.      copyright notice, this list of conditions and the following
  27.      disclaimer in the documentation and/or other materials provided
  28.      with the distribution.
  29.  
  30.   3. Redistributions of any form whatsoever, as well as all
  31.      advertising materials mentioning features or use of this
  32.      software (if any), must include the following acknowledgment:
  33.      "This product includes software developed by Dmitry I. Platonoff".
  34.  
  35.   4. The names "SysBar/2" and "Dmitry I. Platonoff" must not be
  36.      used to endorse or promote products derived from this software
  37.      without prior written permission. For such permission, please
  38.      contact dplatonoff@canada.com.
  39.  
  40.   5. Products derived from this software may not be called
  41.      "SysBar/2" nor may "Dmitry I. Platonoff" appear in their
  42.      contributor lists without prior written permission.
  43.  
  44.   ..................................................................
  45.  
  46.   DISCLAIMER
  47.   ~~~~~~~~~~
  48.   THIS SOFTWARE IS PROVIDED BY THE AUTHOR OR CONTRIBUTORS "AS IS"
  49.   AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  50.   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  51.   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  52.   AUTHOR OR THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  53.   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  54.   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  55.   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  56.   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  57.   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  58.   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  59.   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  60.  
  61. */
  62.  
  63. #define __IBMCPP__
  64.  
  65. #define INCL_BASE
  66. #define INCL_DOSDATETIME
  67. #define INCL_DOSDEVICES
  68. #define INCL_DOSDEVIOCTL
  69. #define INCL_DOSERRORS
  70. #define INCL_DOSEXCEPTIONS
  71. #define INCL_DOSFILEMGR
  72. #define INCL_DOSNMPIPES
  73. #define INCL_DOSPROCESS
  74. #define INCL_DOSSEMAPHORES
  75. #define INCL_ERRORS
  76. #define INCL_GPI
  77. #define INCL_MODULEMGR
  78. #define INCL_DOSNLS
  79. #define INCL_WIN
  80.  
  81. #include <os2.h>
  82. #include <process.h>
  83. #include <stdio.h>
  84. #include <stdlib.h>
  85. #include <string.h>
  86. #include <time.h>
  87. #include "..\SysBar2.h"
  88. #include "sb2_pipe_res.h"
  89. #include "cpuload\pscoll.h"
  90. #include "cpuload\dosqss.h"
  91.  
  92. extern "C" {
  93. #include <netdb.h>
  94. #include <netinet/in.h>
  95. #include <sys/ioctl.h>
  96. #include <sys/socket.h>
  97. #include <net/if.h>
  98. }
  99.  
  100. typedef unsigned long long ULLONG;
  101.  
  102. extern "C" {
  103.   APIRET16 APIENTRY16 Dos16MemAvail( PULONG pulAvailMem );
  104. }
  105.  
  106. //DosPerfSysCall
  107. typedef APIRET ( APIENTRY DOSPERFSYSCALL ) ( ULONG ulCommand, ULONG ulParm1,
  108.   ULONG ulParm2, ULONG ulParm3 );
  109. typedef struct _CPUUTIL
  110. {
  111.   ULONG ulTimeLow;     /* Low 32 bits of time stamp      */
  112.   ULONG ulTimeHigh;    /* High 32 bits of time stamp     */
  113.   ULONG ulIdleLow;     /* Low 32 bits of idle time       */
  114.   ULONG ulIdleHigh;    /* High 32 bits of idle time      */
  115.   ULONG ulBusyLow;     /* Low 32 bits of busy time       */
  116.   ULONG ulBusyHigh;    /* High 32 bits of busy time      */
  117.   ULONG ulIntrLow;     /* Low 32 bits of interrupt time  */
  118.   ULONG ulIntrHigh;    /* High 32 bits of interrupt time */
  119. } CPUUTIL;
  120. HMODULE hmDosCall1 = NULLHANDLE;
  121. DOSPERFSYSCALL* dpsc = NULL;
  122. /* Convert 8-byte (low, high) time value to ULLONG */
  123. #define LL2F(high, low) ((ULLONG(high)<<32)+ULLONG(low))
  124. #define CMD_KI_RDCNT          (0x63)
  125. #define CMD_KI_ENABLE         (0x60)
  126. // Maximal number of CPUs
  127. #define CPUS (4)
  128.  
  129. typedef unsigned long ( _System INET_ADDR ) ( char *pszAddr );
  130. typedef struct hostent * ( _System GETHOSTBYNAME ) ( char *pszHostname );
  131. typedef unsigned short ( _System BSWAP ) ( unsigned short usValue );
  132. typedef int ( _System SOCKET ) ( int iDomain, int iType, int iProtocol );
  133. typedef int ( _System SOCLOSE ) ( int iSocket );
  134. typedef int ( _System SOIOCTL ) ( int iSocket, int iCommand, char *pBuf, int iBufSize );
  135. typedef int ( _System CONNECT ) ( int iSocket, struct sockaddr *Name, int iNameSize );
  136. typedef int ( _System RECV ) ( int iSocket, char *pBuf, int iBufSize, int iFlags );
  137. typedef int ( _System SEND ) ( int iSocket, char *pBuf, int iBufSize, int iFlags );
  138.  
  139. INET_ADDR* InetAddr = NULL;
  140. GETHOSTBYNAME* GetHostByName = NULL;
  141. BSWAP* BSwap = NULL;
  142. SOCKET* Socket = NULL;
  143. SOCLOSE* SoClose = NULL;
  144. SOIOCTL* SoIOCtl = NULL;
  145. CONNECT* Connect = NULL;
  146. RECV* Recv = NULL;
  147. SEND* Send = NULL;
  148.  
  149. typedef struct _Pop3URL
  150. {
  151.   char* pszUsername;
  152.   char* pszPassword;
  153.   char* pszHost;
  154.   int iPort;
  155.   char pData[1];
  156. } Pop3URL;
  157.  
  158. // arbitrary magic constant
  159. #define TRAF_INIT 0x98765432u
  160. typedef struct _TrafData
  161. {
  162.   ULONG uInitialized;
  163.   ULLONG lMaxCPS;
  164.   ULLONG lBytes;
  165.   int iLastOctets;
  166.   ULONG uInitialOctets;
  167.   time_t tInitialTime;
  168.   time_t tLastTime;
  169. } TrafData;
  170.  
  171. HMODULE hmTCP32DLL = NULLHANDLE;
  172. HMODULE hmSo32DLL = NULLHANDLE;
  173. const int iTCPCallCount = 3;
  174. const int iSocketCallCount = 9;
  175. char *pszSocketCalls[iSocketCallCount] =
  176. {
  177.   "INET_ADDR", "GETHOSTBYNAME", "BSWAP",
  178.   "SOCKET", "SOCLOSE", "IOCTL", "CONNECT", "RECV", "SEND"
  179. };
  180. PFN* pSocketFns[iSocketCallCount] =
  181. {
  182.   ( PFN* ) &InetAddr,
  183.   ( PFN* ) &GetHostByName,
  184.   ( PFN* ) &BSwap,
  185.   ( PFN* ) &Socket,
  186.   ( PFN* ) &SoClose,
  187.   ( PFN* ) &SoIOCtl,
  188.   ( PFN* ) &Connect,
  189.   ( PFN* ) &Recv,
  190.   ( PFN* ) &Send
  191. };
  192.  
  193.  
  194. // Config value processing routines ------------------------------------------
  195. inline int strcmp2( char *s1, char *s2, int iDefault = -1 )
  196. {
  197.   if ( ! s1 || ! s2 ) return iDefault;
  198.   else return strcmp( s1, s2 );
  199. }
  200.  
  201. inline int atoi2( char *s, int iDefault = 0 )
  202. {
  203.   if ( s && *s ) return atoi( s );
  204.   else return iDefault;
  205. }
  206.  
  207.  
  208.  
  209. HAB hab;
  210. HWND hwPipeFrame = NULLHANDLE;
  211. HWND hwPipeClient = NULLHANDLE;
  212. HWND hmPopupMenu = NULLHANDLE;
  213. HMODULE hmSysBar2Dll = NULLHANDLE;
  214. //HDC hMemDC = NULLHANDLE;
  215. //HPS hMemPS = NULLHANDLE;
  216. //HBITMAP hbMem = NULLHANDLE;
  217.  
  218. FATTRS fatDesc;
  219. FATTRS fatCell;
  220. FONTDLG fd;
  221. char szFamilyname[FACESIZE] = "";
  222. char szDescFontSection[] = "desc_font";
  223. char szCellFontSection[] = "pipe_font";
  224.  
  225. static short int bLastVisible = 0;
  226. short int iTopmost = 1;
  227. short int iLarge = 0;
  228. short int bClearIt = 0;
  229. short int iBindToCorner = 0;
  230. short int bLockPosition = 0;
  231. int iOrientation = 1;
  232. int iCellSize[4] = { 20, 27, 20, 20 };
  233. DescWindow *pPipeDesc;
  234. //int iPipeBackground = 0;
  235. short int bAlienMenu = 0;
  236. int iDefaultTextColor = 0;
  237. int iDefaultBackColor = 0;
  238.  
  239. char szDefaultColor[] = "-default-";
  240.  
  241. void SB2d_FillColorList( HWND hwnd, ULONG ulID, int iSelected )
  242. {
  243.   WinSendDlgItemMsg( hwnd, ulID, LM_INSERTITEM, ( MPARAM )
  244.     LIT_END, MPFROMP( szDefaultColor ) );
  245.   SB2_FillColorList( hwnd, ulID, iSelected );
  246. }
  247.  
  248. int SB2d_ColorValue( int iIndex, int iDefault )
  249. {
  250.   return SB2_ColorValue( iIndex ? iIndex - 1 : iDefault );
  251. }
  252.  
  253. char* SB2d_ColorName( int iIndex )
  254. {
  255.   return ( iIndex ? SB2_ColorName( iIndex - 1 ) : szDefaultColor );
  256. }
  257.  
  258. int SB2d_ColorA2I( char *pszName )
  259. {
  260.   return
  261.     ( strcmp( pszName, szDefaultColor ) ? SB2_ColorA2I( pszName ) + 1 : 0 );
  262. }
  263.  
  264.  
  265.  
  266.  
  267. int iCellToSetup = -1;
  268. HWND hwLogToUpdate = NULLHANDLE;
  269.  
  270.  
  271.  
  272. #define NO_UseOwn  0x10
  273. #define NO_UseGb   0x08
  274. #define NO_UseMb   0x04
  275. #define NO_UseKb   0x02
  276. #define NO_Useb    0x01
  277. typedef struct
  278. {
  279.   int bUseOptions;
  280.   int iGbLimit;
  281.   int iMbLimit;
  282.   int iKbLimit;
  283.   char szGbName[8];
  284.   char szMbName[8];
  285.   char szKbName[8];
  286.   char szbName[8];
  287. } NumberOptions;
  288. NumberOptions DefaultNumberOptions = { 0xF, 10, 10, 10, "Gb", "Mb", "Kb", "b" };
  289. char szNumberSection[] = "numbers";
  290. char szNumberDefault[] = "default";
  291. char szMiscSection[] = "misc";
  292. NumberOptions *pCurrentOptionsSet = &DefaultNumberOptions;
  293.  
  294. void SaveNumberOptions( FILE *f, NumberOptions *pOptions )
  295. {
  296.   fprintf( f, "%i,%i,%i,%i,%s,%s,%s,%s", pOptions->bUseOptions,
  297.     pOptions->iGbLimit, pOptions->iMbLimit, pOptions->iKbLimit,
  298.     pOptions->szGbName, pOptions->szMbName, pOptions->szKbName, pOptions->szbName );
  299. }
  300.  
  301. void LoadNumberOptions( char *s, NumberOptions *pOptions )
  302. {
  303.   memset( pOptions, 0, sizeof ( NumberOptions ) );
  304.   s = SB2_ParseValue( s, pOptions->bUseOptions );
  305.   s = SB2_ParseValue( s, pOptions->iGbLimit );
  306.   s = SB2_ParseValue( s, pOptions->iMbLimit );
  307.   s = SB2_ParseValue( s, pOptions->iKbLimit );
  308.   s = SB2_ParseValue( s, pOptions->szGbName );
  309.   s = SB2_ParseValue( s, pOptions->szMbName );
  310.   s = SB2_ParseValue( s, pOptions->szKbName );
  311.   s = SB2_ParseValue( s, pOptions->szbName );
  312. }
  313.  
  314. int iPipeCount = 0;
  315. HEV hevPipeGuard;
  316. HEV hevTimed;
  317. HEV hevHeavyTimed;
  318. const int iPipeBufSize = 128;
  319. UCHAR PipeBuffer[iPipeBufSize];
  320.  
  321. #define Condition_Off      0
  322. #define Condition_LessThan 1
  323. #define Condition_EqualsTo 2
  324. #define Condition_MoreThan 3
  325. char* pszConditionTitles[] = { "off", "<", "=", ">" };
  326. const int iColorConditionCount = 3;
  327. typedef struct
  328. {
  329.   short int iCondition;
  330.   char szText[32];
  331.   int iTextColor;
  332.   int iBackColor;
  333. } ColorCondition;
  334.  
  335. typedef struct
  336. {
  337.   int iCellStatus;
  338.   int iCellType;
  339.   int iCellTextColor;
  340.   int iCellBackColor;
  341.   int iCellSeconds;
  342.   int iCellLogBufferSize;
  343.   char szCellDesc[64];
  344.   char szCellPrefix[64];
  345.   char szCellEmpty[64];
  346.   char szCellClickApp[256];
  347.   char szCellChangeApp[256];
  348.   char szCellLogFile[256];
  349.   char* pszCellLog;
  350.   NumberOptions noCellOptions;
  351.   char szCellData1[256];
  352.   ColorCondition Conditions[iColorConditionCount];
  353.  
  354.   int iCellWidth;
  355.   int iCellLazyCounter;
  356.   int iCellCounter;
  357.   int iCellIndex;
  358.   LHANDLE hCellHandle;
  359.   char szCellData[iPipeBufSize];
  360.   char szCellData0[iPipeBufSize];
  361. } CellData;
  362. CellData *pCells = NULL;
  363. int iCellCount = 0;
  364. int iCellIndexes = 0;
  365. char szCellsCfg[] = "cells";
  366. char szCellDelimiters[] = ",";
  367. const int iLazySeconds = 10;
  368.  
  369. char *pszCellTypes1[] =
  370. {
  371.   "CPU load meter",
  372.   "available physical memory",
  373.   "drive/partition free space",
  374.   "file monitor",
  375.   "battery status",
  376.   "clock",
  377.   "calendar",
  378.   "system uptime",
  379.   "system processes",
  380.   "POP3 mailbox",
  381.   "IP traffic: incoming",
  382.   "IP traffic: outgoing",
  383.   "custom pipe listener",
  384.   "AICQ pipe: ICQ status",
  385.   "Keyboard Layer/2 pipe: current layout",
  386.   "SETI@HOME pipe: completion percentage",
  387.   "ThermoProtect pipe: fan #1 speed",
  388.   "ThermoProtect pipe: fan #2 speed",
  389.   "ThermoProtect pipe: fan #3 speed",
  390.   "ThermoProtect pipe: temperature probe #1, C",
  391.   "ThermoProtect pipe: temperature probe #1, F",
  392.   "ThermoProtect pipe: temperature probe #2, C",
  393.   "ThermoProtect pipe: temperature probe #2, F",
  394.   "ThermoProtect pipe: temperature probe #3, C",
  395.   "ThermoProtect pipe: temperature probe #3, F",
  396.   "ThermoProtect pipe: CPU core voltage A",
  397.   "ThermoProtect pipe: CPU core voltage B",
  398.   "ThermoProtect pipe: +3.3 voltage",
  399.   "ThermoProtect pipe: +5.0 voltage",
  400.   "ThermoProtect pipe: -5.0 voltage",
  401.   "ThermoProtect pipe: +12.0 voltage",
  402.   "ThermoProtect pipe: -12.0 voltage",
  403.   "ThermoProtect pipe: CMOS battery voltage",
  404.   "ThermoProtect pipe: +5.0 standby voltage",
  405.   "ThermoProtect pipe: case intrusion"
  406. };
  407. char *pszCellTypes2[] =
  408. {
  409.   "cpuload",
  410.   "physmem",
  411.   "freespace",
  412.   "files",
  413.   "power",
  414.   "clock",
  415.   "calendar",
  416.   "uptime",
  417.   "processes",
  418.   "pop3peek",
  419.   "trafin",
  420.   "trafout",
  421.   "pipe",
  422.   "pipe4aicq",
  423.   "pipe4layer",
  424.   "pipe4seti",
  425.   "pipe4TP-fan1",
  426.   "pipe4TP-fan2",
  427.   "pipe4TP-fan3",
  428.   "pipe4TP-temp#1",
  429.   "pipe4TP-temp#1F",
  430.   "pipe4TP-temp#2",
  431.   "pipe4TP-temp#2F",
  432.   "pipe4TP-temp#3",
  433.   "pipe4TP-temp#3F",
  434.   "pipe4TP-VcoreA",
  435.   "pipe4TP-VcoreB",
  436.   "pipe4TP-3.3V",
  437.   "pipe4TP-5V",
  438.   "pipe4TP-m5V",
  439.   "pipe4TP-12V",
  440.   "pipe4TP-m12V",
  441.   "pipe4TP-CMOS",
  442.   "pipe4TP-VSB",
  443.   "pipe4TP-case"
  444. };
  445. #define MCT_CPULoad        0
  446. #define MCT_PhysMem        1
  447. #define MCT_FreeSpace      2
  448. #define MCT_FileSize       3
  449. #define MCT_Power          4
  450. #define MCT_Clock          5
  451. #define MCT_Calendar       6
  452. #define MCT_Uptime         7
  453. #define MCT_Processes      8
  454. #define MCT_TCPDLLs0       9
  455. #define MCT_POP3           9
  456. #define MCT_TrafIn        10
  457. #define MCT_TrafOut       11
  458. #define MCT_TCPDLLs1      11
  459. #define MCT_Pipe          12
  460. #define MCT_Pipe4AICQ     13
  461. #define MCT_Pipe4Layer    14
  462. #define MCT_Pipe4SETI     15
  463. #define MCT_Pipe4TPfan1   16
  464. #define MCT_Pipe4TPfan2   17
  465. #define MCT_Pipe4TPfan3   18
  466. #define MCT_Pipe4TPtemp1  19
  467. #define MCT_Pipe4TPtemp1F 20
  468. #define MCT_Pipe4TPtemp2  21
  469. #define MCT_Pipe4TPtemp2F 22
  470. #define MCT_Pipe4TPtemp3  23
  471. #define MCT_Pipe4TPtemp3F 24
  472. #define MCT_Pipe4TPVcoreA 25
  473. #define MCT_Pipe4TPVcoreB 26
  474. #define MCT_Pipe4TP3V     27
  475. #define MCT_Pipe4TP5V     28
  476. #define MCT_Pipe4TPm5V    39
  477. #define MCT_Pipe4TP12V    30
  478. #define MCT_Pipe4TPm12V   31
  479. #define MCT_Pipe4TPCMOS   32
  480. #define MCT_Pipe4TPVSB    33
  481. #define MCT_Pipe4TPcase   34
  482. const int iCellTypeCount = 35;
  483.  
  484. #define Cell_Log_On            0x1
  485. #define Cell_Log_Timestamping  0x2
  486. #define Cell_Log_Append        0x4
  487. #define Cell_Enabled           0x8
  488. #define Cell_Click_App        0x10
  489. #define Cell_Change_App       0x20
  490. #define Cell_Expire           0x40
  491. #define Cell_Check0           0x80
  492. #define Cell_Check1          0x100
  493. #define Cell_Check2          0x200
  494. #define Cell_Check3          0x400
  495. #define Cell_LazyShrink      0x800
  496.  
  497. char *pszCellParamNames[] = { "", "", "Drive", "File",
  498.   "", "", "", "", "", "URL", "Interf.", "Interf.", "Pipe" };
  499.  
  500. const int iHiddenCheckCount = 4;
  501. char *pszCellCheckNames[][iHiddenCheckCount] =
  502. {
  503.   { "~Limit to 99%",                              //CPU load meter
  504.     "~Use newer DosPerfSysCall method", "~Second CPU", NULL },
  505.   { NULL, NULL, NULL, NULL },                     //physical memory
  506.   { NULL, NULL, NULL, NULL },                     //disk free space
  507.   { "Show ~count", "Show ~size", NULL, NULL },    //file monitor
  508.   { NULL, NULL, NULL, NULL },                     //battery status
  509.   { "Show ~seconds", "AM/PM ~mode", NULL, NULL }, //clock
  510.   { "Show ~day of the week", "Show ~month",       //calendar
  511.     "Show ~year", "Display month ~name" },
  512.   { "Show ~seconds", "Show ~days", NULL, NULL },  //uptime
  513.   { "Show ~active task count",                    //processes
  514.     "Show ~thread count", "Show ~module count",
  515.     /*"Show ~process count"*/ NULL  },
  516.   { "Show message ~count", "Show total ~size",    //POP3
  517.     "Show e~rrors", "Show server ~output" },
  518.   { "Show ~current CPS", "Show ~average CPS",     //incoming traffic
  519.     "Show ~peak CPS", "Show ~total byte amount" },
  520.   { "Show ~current CPS", "Show ~average CPS",     //outgoing traffic
  521.     "Show ~peak CPS", "Show ~total byte amount" },
  522.   { NULL, NULL, NULL, NULL }                      //pipe reader
  523. };
  524.  
  525. char *pszCellDescs[iCellTypeCount] =
  526. {
  527.   "CPU Load",                                       //CPU load meter
  528.   "Available Physical Memory",                      //physical memory
  529.   "Drive ",                                         //disk free space
  530.   "Files",                                          //file monitor
  531.   "Battery Status",                                 //battery status
  532.   "Clock",                                          //clock
  533.   "Calendar",                                       //calendar
  534.   "System Uptime",                                  //uptime
  535.   "Active Tasks/Threads/Modules", //"/Processes"    //processes
  536.   "POP3 Mailbox",                                   //POP3
  537.   "Incoming IP Traffic",                            //incoming traffic
  538.   "Outgoing IP Traffic",                            //outgoing traffic
  539.   "Pipe",                                           //pipe reader
  540.   "AICQ Status",                                    //AICQ pipe
  541.   "Keyboard Layer/2",                               //Layer/2 pipe
  542.   "SETI@HOME Completion Percentage",                //SETI@HOME pipe
  543.   "Fan #1 Speed, RPM",                              //fan1 speed
  544.   "Fan #2 Speed, RPM",                              //fan2 speed
  545.   "Fan #3 Speed, RPM",                              //fan3 speed
  546.   "Temperature Probe #1, Celsius",                  //temperature1C
  547.   "Temperature Probe #1, Fahrenheit",               //temperature1F
  548.   "Temperature Probe #2, Celsius",                  //temperature2C
  549.   "Temperature Probe #2, Fahrenheit",               //temperature2F
  550.   "Temperature Probe #3, Celsius",                  //temperature3C
  551.   "Temperature Probe #3, Fahrenheit",               //temperature3F
  552.   "CPU Core Voltage A, Volts",                      //core voltage A
  553.   "CPU Core Voltage B, Volts",                      //core voltage B
  554.   "+3.3 Voltage, Volts",                            //+3.3 voltage
  555.   "+5.0 Voltage, Volts",                            //+5.0 voltage
  556.   "-5.0 Voltage, Volts",                            //-5.0 voltage
  557.   "+12.0 Voltage, Volts",                           //+12.0 voltage
  558.   "-12.0 Voltage, Volts",                           //-12.0 voltage
  559.   "CMOS Battery, Volts",                            //CMOS cattery
  560.   "+5.0 Standby Voltage, Volts",                    //+5.0 standby voltage
  561.   "Case Intrusion"                                  //case intrusion
  562. };
  563.  
  564. char *pszCellPrefixes[iCellTypeCount] =
  565. {
  566.   "CPU: ",   //CPU load meter
  567.   "Mem: ",   //physical memory
  568.   "",        //disk free space
  569.   "",        //file monitor
  570.   "",        //battery status
  571.   "",        //clock
  572.   "",        //calendar
  573.   "",        //uptime
  574.   "",        //processes
  575.   "Mail: ",  //POP3
  576.   "In: ",    //incoming traffic
  577.   "Out: ",   //outgoing traffic
  578.   "",        //pipe reader
  579.   "",        //AICQ pipe
  580.   "",        //Layer/2 pipe
  581.   "SETI: ",  //SETI@HOME pipe
  582.   "Fan1: ",  //fan1 speed
  583.   "Fan2: ",  //fan2 speed
  584.   "Fan3: ",  //fan3 speed
  585.   "Temp1: ", //temperature1C
  586.   "Temp1: ", //temperature1F
  587.   "Temp2: ", //temperature2C
  588.   "Temp2: ", //temperature2F
  589.   "Temp3: ", //temperature3C
  590.   "Temp3: ", //temperature3F
  591.   "CoreA: ", //core voltage A
  592.   "CoreB: ", //core voltage B
  593.   "+3.3: ",  //+3.3 voltage
  594.   "+5.0: ",  //+5.0 voltage
  595.   "-5.0: ",  //-5.0 voltage
  596.   "+12.0: ", //+12.0 voltage
  597.   "-12.0: ", //-12.0 voltage
  598.   "CMOS: ",  //CMOS cattery
  599.   "+5V: ",   //+5.0 standby voltage
  600.   "Case: "   //case intrusion
  601. };
  602.  
  603. char *pszCustomPipes[] =
  604. {
  605.   "\\PIPE\\AICQ",
  606.   "\\PIPE\\KBDLAY2",
  607.   "\\PIPE\\SETI-PROG.SB2",
  608.   "\\PIPE\\TP-fan1",
  609.   "\\PIPE\\TP-fan2",
  610.   "\\PIPE\\TP-fan3",
  611.   "\\PIPE\\TP-temp1",
  612.   "\\PIPE\\TP-temp1F",
  613.   "\\PIPE\\TP-temp2",
  614.   "\\PIPE\\TP-temp2F",
  615.   "\\PIPE\\TP-temp3",
  616.   "\\PIPE\\TP-temp3F",
  617.   "\\PIPE\\TP-VcoreA",
  618.   "\\PIPE\\TP-VcoreB",
  619.   "\\PIPE\\TP-3.3V",
  620.   "\\PIPE\\TP-5V",
  621.   "\\PIPE\\TP-m5V",
  622.   "\\PIPE\\TP-12V",
  623.   "\\PIPE\\TP-m12V",
  624.   "\\PIPE\\TP-CMOS",
  625.   "\\PIPE\\TP-VSB",
  626.   "\\PIPE\\TP-case"
  627. };
  628.  
  629.  
  630. const int iHiddenControlCount = 6;
  631. int iHiddenControls[iHiddenControlCount] =
  632. {
  633.   D_Cell_Expire,
  634.   D_Cell_TimeoutT,
  635.   D_Cell_Name,
  636.   D_Cell_BrowseFile,
  637.   D_Cell_CopyrightT,
  638.   D_Cell_Choice,
  639. };
  640. int iHiddenControlSets[][iHiddenControlCount] =
  641. {
  642.   { 0, 1, 0, 0, 1, 0 },  //CPU load meter controls
  643.   { 0, 1, 0, 0, 0, 0 },  //available physical memory
  644.   { 0, 1, 0, 0, 0, 1 },  //disk free space monitor controls
  645.   { 0, 1, 1, 1, 0, 0 },  //file monitor controls
  646.   { 0, 1, 0, 0, 0, 0 },  //battery status monitor controls
  647.   { 0, 1, 0, 0, 0, 0 },  //clock controls
  648.   { 0, 1, 0, 0, 0, 0 },  //calendar controls
  649.   { 0, 1, 0, 0, 0, 0 },  //uptime controls
  650.   { 0, 1, 0, 0, 0, 0 },  //processes controls
  651.   { 0, 1, 1, 0, 0, 0 },  //POP3 peeker controls
  652.   { 0, 1, 0, 0, 0, 1 },  //incoming traffic monitor controls
  653.   { 0, 1, 0, 0, 0, 1 },  //outgoing traffic monitor controls
  654.   { 1, 0, 1, 0, 0, 0 }   //pipe reader controls
  655. };
  656.  
  657.  
  658. // Just a dummy data structure
  659. typedef struct
  660. {
  661.   short int iSize;
  662. } DummyData;
  663. DummyData DummyInit = { sizeof ( DummyData ) };
  664.  
  665. // Configuration file stuff
  666. char *pszIniFile = NULL;
  667. char szSysBar2Pipe[] = "SysBar2_Piper";
  668. char *pszYesNo[2] = { "no", "yes" };
  669.  
  670. int iWindowHeight = 0, iWindowWidth = 8;
  671.  
  672. enum ErrorIDs
  673. {
  674.   APM_CantInit    = 0,
  675.   P3E_UnknownHost = 1,
  676.   P3E_Socket      = 2,
  677.   P3E_CantReach   = 3,
  678.   P3E_UserSnd     = 4,
  679.   P3E_UserRcv     = 5,
  680.   P3E_User        = 6,
  681.   P3E_PasswordSnd = 7,
  682.   P3E_PasswordRcv = 8,
  683.   P3E_Password    = 9,
  684.   P3E_StatSnd     = 10,
  685.   P3E_StatRcv     = 11,
  686.   P3E_Stat        = 12
  687. };
  688. const char iErrorCount = 13;
  689.  
  690. char szErrorSection[] = "errors";
  691. char* pszErrorIDs[] =
  692. {
  693.   "APM_CantInit",
  694.   "P3E_UnknownHost",
  695.   "P3E_Socket",
  696.   "P3E_CantReach",
  697.   "P3E_UserSnd",
  698.   "P3E_UserRcv",
  699.   "P3E_User",
  700.   "P3E_PasswordSnd",
  701.   "P3E_PasswordRcv",
  702.   "P3E_Password",
  703.   "P3E_StatSnd",
  704.   "P3E_StatRcv",
  705.   "P3E_Stat"
  706. };
  707.  
  708. char* pszErrors[] =
  709. {
  710.   "APM error",                              //APM_CantInit
  711.   "unknown host %s",                        //P3E_UnknownHost
  712.   "can't create socket",                    //P3E_Socket
  713.   "can't reach %s",                         //P3E_CantReach
  714.   "error sending username %s",              //P3E_UserSnd
  715.   "error receiving reply for username %s",  //P3E_UserRcv
  716.   "no such user: %s",                       //P3E_User
  717.   "error sending password for user %s",     //P3E_PasswordSnd
  718.   "error receiving PASS reply for user %s", //P3E_PasswordRcv
  719.   "wrong password for %s",                  //P3E_Password
  720.   "error sending STAT command for %s",      //P3E_StatSnd
  721.   "error receiving STAT reply for user %s", //P3E_StatRcv
  722.   "can't make STAT for %s"                  //P3E_Stat
  723. };
  724.  
  725.  
  726. const int iDaysOfTheWeek = 7;
  727. char szDaysOfTheWeek[iDaysOfTheWeek][32] =
  728.   { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
  729.  
  730. const int iMonths = 12;
  731. char szMonths[iMonths][32] =
  732. {
  733.   "Jan", "Feb", "Mar", "Apr", "May", "June",
  734.   "July", "Aug", "Sep", "Oct", "Nov", "Dec"
  735. };
  736.  
  737. #define FDT_Date   1
  738. #define FDT_Time   2
  739. #define FDT_Uptime 4
  740.  
  741. void FormatNumber( char *pszBuf, NumberOptions *pOptions, ULLONG dNumber,
  742.   int iDisplayed = 0 )
  743. {
  744.   pszBuf += strlen( pszBuf );
  745.   if ( iDisplayed ) *( pszBuf++ ) = '/';
  746.   if ( ( pOptions->bUseOptions & NO_UseOwn ) != NO_UseOwn )
  747.     pOptions = &DefaultNumberOptions;
  748.   char *pszName = pOptions->szbName;
  749.  
  750.   if ( ( pOptions->bUseOptions & NO_UseGb ) &&
  751.        ( dNumber/(1u<<30) >= pOptions->iGbLimit || !(pOptions->bUseOptions & (NO_UseMb | NO_UseKb | NO_Useb)) )
  752.      )
  753.   {
  754.     pszName = pOptions->szGbName;
  755.     dNumber /= (1u<<30);
  756.   }
  757.   else if ( (pOptions->bUseOptions & NO_UseMb) &&
  758.             ( dNumber/(1u<<20) >= pOptions->iMbLimit || !(pOptions->bUseOptions & (NO_UseKb | NO_Useb)) ) 
  759.           )
  760.   {
  761.     pszName = pOptions->szMbName;
  762.     dNumber /= (1u<<20);
  763.   }
  764.   else if ( (pOptions->bUseOptions & NO_UseKb) &&
  765.             ( dNumber/(1u<<10) >= pOptions->iKbLimit || !(pOptions->bUseOptions & NO_Useb) )
  766.           )
  767.   {
  768.     pszName = pOptions->szKbName;
  769.     dNumber /= (1u<<10);
  770.   }
  771.  
  772.   sprintf( pszBuf, "%I64u%s", dNumber, pszName );
  773. }
  774.  
  775. void FormatCount( char* pszBuf, int iCount, ULLONG dSize, CellData* pCell )
  776. {
  777.   if ( iCount )
  778.   {
  779.     if ( pCell->iCellStatus & Cell_Check0 )
  780.     {
  781.       sprintf( pszBuf, "%i", iCount );
  782.       if ( pCell->iCellStatus & Cell_Check1 )
  783.         strcat( pszBuf, " (" );
  784.     }
  785.     if ( pCell->iCellStatus & Cell_Check1 )
  786.     {
  787.       FormatNumber( pszBuf, &( pCell->noCellOptions ), dSize );
  788.       if ( pCell->iCellStatus & Cell_Check0 )
  789.         strcat( pszBuf, ")" );
  790.     }
  791.   }
  792. }
  793.  
  794. void FormatDateTime( char *pszBuf, int iTimeOptions, int iDateOptions = 0,
  795.   short siDateTime = FDT_Time )
  796. {
  797.   DATETIME dtIn = { 0 };
  798.   COUNTRYCODE CountryCode = { 0 };
  799.   COUNTRYINFO CountryInfo = { 0 };
  800.   ULONG ulL = 0;
  801.   DosQueryCtryInfo( sizeof ( COUNTRYINFO ), &CountryCode,
  802.     &CountryInfo, &ulL );
  803.  
  804.   pszBuf[0] = 0;
  805.  
  806.   if ( siDateTime & FDT_Uptime )
  807.   {
  808.     DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, &ulL, sizeof ( ULONG ) );
  809.     ulL /= 1000L;
  810.     dtIn.seconds = ( UCHAR ) ( ulL % 60L );
  811.     ulL /= 60L;
  812.     dtIn.minutes = ( UCHAR ) ( ulL % 60L );
  813.     ulL /= 60L;
  814.     if ( iTimeOptions & Cell_Check1 )
  815.     {
  816.       ULONG ulDays = ulL / 24L;
  817.       if ( ulDays )
  818.         sprintf( pszBuf, "%li day%s ", ulDays, ulDays > 1 ? "s" : "" );
  819.       ulL %= 24L;
  820.     }
  821.     sprintf( pszBuf + strlen( pszBuf ), "%li%s%02i", ulL,
  822.       CountryInfo.szTimeSeparator, short ( dtIn.minutes ) );
  823.     if ( iTimeOptions & Cell_Check0 ) sprintf( pszBuf + strlen( pszBuf ),
  824.       "%s%02i", CountryInfo.szTimeSeparator, short ( dtIn.seconds ) );
  825.   }
  826.   else
  827.   {
  828.     DosGetDateTime( &dtIn );
  829.  
  830.     if ( siDateTime & FDT_Time )
  831.     {
  832.       int iAMPM = 0;
  833.       if ( iTimeOptions & Cell_Check1 )
  834.       {
  835.         if ( dtIn.hours >= 12 )
  836.         {
  837.           dtIn.hours -= 12;
  838.           iAMPM = 1;
  839.         }
  840.         if ( dtIn.hours == 0 ) dtIn.hours = 12;
  841.       }
  842.       sprintf( pszBuf, "%i%s%02i", short ( dtIn.hours ),
  843.         CountryInfo.szTimeSeparator, short ( dtIn.minutes ) );
  844.       if ( iTimeOptions & Cell_Check0 ) sprintf( pszBuf + strlen( pszBuf ),
  845.         "%s%02i", CountryInfo.szTimeSeparator, short ( dtIn.seconds ) );
  846.       if ( iTimeOptions & Cell_Check1 ) strcat( pszBuf, iAMPM ? " pm" : " am" );
  847.     }
  848.  
  849.     if ( siDateTime & FDT_Date )
  850.     {
  851.       if ( siDateTime & FDT_Time ) strcat( pszBuf, " " );
  852.  
  853.       if ( iDateOptions & Cell_Check0 ) sprintf( pszBuf + strlen( pszBuf ),
  854.         "%s, ", szDaysOfTheWeek[dtIn.weekday] );
  855.  
  856.       int n1 = dtIn.day;
  857.       int n3 = ( iDateOptions & Cell_Check2 ) ? dtIn.year : 0;
  858.       char n2[32] = { 0 };
  859.       if ( iDateOptions & Cell_Check1 )
  860.       {
  861.         if ( iDateOptions & Cell_Check3 )
  862.         {
  863.           CountryInfo.szDateSeparator[0] = ' ';
  864.           CountryInfo.szDateSeparator[1] = 0;
  865.           strcpy( n2, szMonths[short ( dtIn.month ) - 1] );
  866.         }
  867.         else sprintf( n2, "%02i", short ( dtIn.month ) );
  868.       }
  869.  
  870.       switch ( CountryInfo.fsDateFmt )
  871.       {
  872.         case 0:
  873.           if ( n2[0] ) sprintf( pszBuf + strlen( pszBuf ), "%s%s",
  874.             n2, CountryInfo.szDateSeparator );
  875.           sprintf( pszBuf + strlen( pszBuf ), "%02i", n1 );
  876.           if ( n3 ) sprintf( pszBuf + strlen( pszBuf ), "%s%02i",
  877.             n2[0] ? CountryInfo.szDateSeparator : " ", short ( n3 ) );
  878.           break;
  879.  
  880.         case 1:
  881.           sprintf( pszBuf + strlen( pszBuf ), "%02i", n1 );
  882.           if ( n2[0] ) sprintf( pszBuf + strlen( pszBuf ), "%s%s",
  883.             CountryInfo.szDateSeparator, n2 );
  884.           if ( n3 ) sprintf( pszBuf + strlen( pszBuf ), "%s%02i",
  885.             n2[0] ? CountryInfo.szDateSeparator : " ", short ( n3 ) );
  886.           break;
  887.  
  888.         case 2:
  889.           if ( n3 ) sprintf( pszBuf + strlen( pszBuf ), "%02i%s",
  890.             short ( n3 ), n2[0] ? CountryInfo.szDateSeparator : " " );
  891.           if ( n2[0] ) sprintf( pszBuf + strlen( pszBuf ), "%s%s",
  892.             n2, CountryInfo.szDateSeparator );
  893.           sprintf( pszBuf + strlen( pszBuf ), "%02i", n1 );
  894.           break;
  895.       }
  896.     }
  897.   }
  898. }
  899.  
  900.  
  901. // Cell config saver ---------------------------------------------------------
  902. void SaveCellCfg( FILE *f )
  903. {
  904.   fprintf( f, "[%s]\ncount=%i", szCellsCfg, iCellCount );
  905.   for ( int i = 0; i < iCellCount; i++ )
  906.   {
  907.     fprintf( f, "\n\ncell%03i=%s,%s,%s,%s,%s,%i,%i", i,
  908.       pszCellTypes2[pCells[i].iCellType],
  909.       SB2d_ColorName( pCells[i].iCellTextColor ),
  910.       pCells[i].szCellDesc, pCells[i].szCellPrefix, pCells[i].szCellEmpty,
  911.       pCells[i].iCellSeconds, pCells[i].iCellStatus );
  912.     fprintf( f, "\ncolors%03i=%s", i,
  913.       SB2d_ColorName( pCells[i].iCellBackColor ) );
  914.     for ( int j = 0; j < iColorConditionCount; j++ ) fprintf( f, ",%s,%s,%s,%s",
  915.       pszConditionTitles[pCells[i].Conditions[j].iCondition],
  916.       pCells[i].Conditions[j].szText,
  917.       SB2d_ColorName( pCells[i].Conditions[j].iTextColor ),
  918.       SB2d_ColorName( pCells[i].Conditions[j].iBackColor ) );
  919.     fprintf( f, "\nchangeapp%03i=%s", i, pCells[i].szCellChangeApp );
  920.     fprintf( f, "\nclickapp%03i=%s", i, pCells[i].szCellClickApp );
  921.     fprintf( f, "\nlog%03i=%i,%s", i,
  922.       pCells[i].iCellLogBufferSize, pCells[i].szCellLogFile );
  923.     switch ( pCells[i].iCellType )
  924.     {
  925.       case MCT_Pipe:
  926.       case MCT_FreeSpace:
  927.       case MCT_FileSize:
  928.       case MCT_POP3:
  929.         fprintf( f, "\ndata%03i=%s", i, pCells[i].szCellData1 );
  930.         break;
  931.       case MCT_TrafIn:
  932.       case MCT_TrafOut:
  933.         fprintf( f, "\ndata%03i=%02d", i, *(int*)pCells[i].szCellData1 );
  934.         break;
  935.     }
  936.     switch ( pCells[i].iCellType )
  937.     {
  938.       case MCT_FreeSpace:
  939.       case MCT_FileSize:
  940.       case MCT_PhysMem:
  941.       case MCT_POP3:
  942.       case MCT_TrafIn:
  943.       case MCT_TrafOut:
  944.         fprintf( f, "\nnumbers%03i=", i );
  945.         SaveNumberOptions( f, &( pCells[i].noCellOptions ) );
  946.         break;
  947.     }
  948.   }
  949.   fprintf( f, "\n\n" );
  950. }
  951.  
  952. // Cell config loader --------------------------------------------------------
  953. void LoadCellCfg( IniFile *pCfg )
  954. {
  955.   iCellCount = atoi2( pCfg->Get( szCellsCfg, "count" ) );
  956.  
  957.   if ( iCellCount )
  958.   {
  959.     if ( ( pCells = new CellData[iCellCount] ) == 0 ) return;
  960.     memset( pCells, 0, sizeof( CellData ) * iCellCount );
  961.     char szTmp[32];
  962.     char *pS;
  963.     for ( int i = 0; i < iCellCount; i++ )
  964.     {
  965.       pCells[i].noCellOptions = DefaultNumberOptions;
  966.       sprintf( szTmp, "cell%03i", i );
  967.  
  968.       if ( ( pS = pCfg->Get( szCellsCfg, szTmp ) ) )
  969.       {
  970.         pS = SB2_ParseValue( pS, szTmp );
  971.         for ( int j = 0; j < iCellTypeCount; j++ )
  972.           if ( ! strcmp( szTmp, pszCellTypes2[j] ) )
  973.           {
  974.             pCells[i].iCellType = j;
  975.             break;
  976.           }
  977.         pS = SB2_ParseValue( pS, szTmp );
  978.         pCells[i].iCellTextColor = SB2d_ColorA2I( szTmp );
  979.         pS = SB2_ParseValue( pS, pCells[i].szCellDesc );
  980.         pS = SB2_ParseValue( pS, pCells[i].szCellPrefix );
  981.         pS = SB2_ParseValue( pS, pCells[i].szCellEmpty );
  982.         pS = SB2_ParseValue( pS, pCells[i].iCellSeconds );
  983.         pCells[i].iCellStatus = Cell_Enabled;
  984.         pS = SB2_ParseValue( pS, pCells[i].iCellStatus );
  985.         if ( pCells[i].iCellType >= MCT_TCPDLLs0 &&
  986.           pCells[i].iCellType <= MCT_TCPDLLs1 && ! hmSo32DLL )
  987.           pCells[i].iCellStatus &= ~Cell_Enabled;
  988.  
  989.         sprintf( szTmp, "colors%03i", i );
  990.         if ( ( pS = pCfg->Get( szCellsCfg, szTmp ) ) )
  991.         {
  992.           pS = SB2_ParseValue( pS, szTmp );
  993.           pCells[i].iCellBackColor = SB2d_ColorA2I( szTmp );
  994.           for ( int j = 0; j < iColorConditionCount && pS; j++ )
  995.           {
  996.             pS = SB2_ParseValue( pS, szTmp );
  997.             for ( int k = 0; k < 4; k++ )
  998.               if ( ! strcmp( szTmp, pszConditionTitles[k] ) )
  999.               {
  1000.                 pCells[i].Conditions[j].iCondition = k;
  1001.                 break;
  1002.               }
  1003.             if ( ! ( pS =
  1004.               SB2_ParseValue( pS, pCells[i].Conditions[j].szText ) ) ) break;
  1005.             pS = SB2_ParseValue( pS, szTmp );
  1006.             pCells[i].Conditions[j].iTextColor = SB2d_ColorA2I( szTmp );
  1007.             if ( pS )
  1008.             {
  1009.               pS = SB2_ParseValue( pS, szTmp );
  1010.               pCells[i].Conditions[j].iBackColor = SB2d_ColorA2I( szTmp );
  1011.             }
  1012.           }
  1013.         }
  1014.  
  1015.         sprintf( szTmp, "changeapp%03i", i );
  1016.         if ( ( pS = pCfg->Get( szCellsCfg, szTmp ) ) )
  1017.           pS = SB2_ParseValue( pS, pCells[i].szCellChangeApp );
  1018.  
  1019.         sprintf( szTmp, "clickapp%03i", i );
  1020.         if ( ( pS = pCfg->Get( szCellsCfg, szTmp ) ) )
  1021.           pS = SB2_ParseValue( pS, pCells[i].szCellClickApp );
  1022.  
  1023.         sprintf( szTmp, "log%03i", i );
  1024.         if ( ( pS = pCfg->Get( szCellsCfg, szTmp ) ) )
  1025.         {
  1026.           pS = SB2_ParseValue( pS, pCells[i].iCellLogBufferSize );
  1027.           pS = SB2_ParseValue( pS, pCells[i].szCellLogFile );
  1028.           if ( ! pCells[i].iCellLogBufferSize )
  1029.             pCells[i].iCellLogBufferSize = 2;
  1030.         }
  1031.         if ( ( pCells[i].iCellStatus & Cell_Log_On ) &&
  1032.           pCells[i].iCellLogBufferSize )
  1033.         {
  1034.           int iLogSize = pCells[i].iCellLogBufferSize * 1024;
  1035.           if ( pCells[i].pszCellLog = new char[iLogSize] )
  1036.             memset( pCells[i].pszCellLog, 0, iLogSize );
  1037.           else pCells[i].iCellStatus &= ~Cell_Log_On;
  1038.         }
  1039.  
  1040.         switch ( pCells[i].iCellType )
  1041.         {
  1042.           case MCT_Pipe:
  1043.           case MCT_FreeSpace:
  1044.           case MCT_FileSize:
  1045.           case MCT_POP3:
  1046.             sprintf( szTmp, "data%03i", i );
  1047.             if ( ( pS = pCfg->Get( szCellsCfg, szTmp ) ) )
  1048.               pS = SB2_ParseValue( pS, pCells[i].szCellData1 );
  1049.             break;
  1050.           case MCT_TrafIn:
  1051.           case MCT_TrafOut:
  1052.             sprintf( szTmp, "data%03i", i );
  1053.             if ( ( pS = pCfg->Get( szCellsCfg, szTmp ) ) )
  1054.               pS = SB2_ParseValue( pS, *(int*)pCells[i].szCellData1 );
  1055.             break;
  1056.         }
  1057.  
  1058.         switch ( pCells[i].iCellType )
  1059.         {
  1060.           case MCT_FreeSpace:
  1061.           case MCT_FileSize:
  1062.           case MCT_PhysMem:
  1063.           case MCT_POP3:
  1064.           case MCT_TrafIn:
  1065.           case MCT_TrafOut:
  1066.             sprintf( szTmp, "numbers%03i", i );
  1067.             if ( ( pS = pCfg->Get( szCellsCfg, szTmp ) ) )
  1068.               LoadNumberOptions( pS, &( pCells[i].noCellOptions ) );
  1069.             break;
  1070.         }
  1071.       }
  1072.     }
  1073.   }
  1074. }
  1075.  
  1076.  
  1077. // Abnormal startup handler --------------------------------------------------
  1078. void AbortStartup( void )
  1079. {
  1080.   PERRINFO pErrInfoBlk;
  1081.   PSZ pszOffSet;
  1082.   PSZ pszErrMsg;
  1083.  
  1084.   if ( ( pErrInfoBlk = WinGetErrorInfo( hab ) ) != ( PERRINFO ) NULL )
  1085.   {
  1086.     pszOffSet = ( ( PSZ ) pErrInfoBlk ) + pErrInfoBlk->offaoffszMsg;
  1087.     pszErrMsg = ( ( PSZ ) pErrInfoBlk ) + *( ( PSHORT ) pszOffSet );
  1088.     if ( ( int ) hwPipeFrame && ( int ) hwPipeClient )
  1089.       WinMessageBox( HWND_DESKTOP, hwPipeFrame, ( PSZ ) pszErrMsg,
  1090.         "SysBar/2 Pipe Monitor startup error :(", 8999,
  1091.         MB_MOVEABLE | MB_ERROR | MB_CANCEL );
  1092.     WinFreeErrorInfo( pErrInfoBlk );
  1093.   }
  1094.   WinPostMsg( hwPipeClient, WM_QUIT, ( MPARAM ) NULL, ( MPARAM ) NULL );
  1095. }
  1096.  
  1097.  
  1098.  
  1099.  
  1100. // Pop-up description window stuff and routines ------------------------------
  1101. int iDescCell = -1;
  1102. int iLastCell = -1;
  1103.  
  1104. void HideDescWindow( void )
  1105. {
  1106.   if ( iDescCell != -1 )
  1107.   {
  1108.     pPipeDesc->Hide();
  1109.     iDescCell = -1;
  1110.   }
  1111. }
  1112.  
  1113. void AdjustDescPos( int x, int y, short int bHideOnly = 1 )
  1114. {
  1115.   if ( x > iWindowWidth - 7 || x < 4 || y > iWindowHeight - 2 || y < 2 ||
  1116.     bAlienMenu )
  1117.   {
  1118.     HideDescWindow();
  1119.     return;
  1120.   }
  1121.   int iXOffset = 4;
  1122.   for ( int i = 0; i < iCellCount; i++ ) if ( pCells[i].iCellWidth )
  1123.   {
  1124.     if ( x >= iXOffset && x < ( iXOffset + pCells[i].iCellWidth ) )
  1125.     {
  1126.       if ( iDescCell == i ) return;
  1127.       iLastCell = iDescCell = i;
  1128.       break;
  1129.     }
  1130.     iXOffset += pCells[i].iCellWidth;
  1131.   }
  1132.   if ( i >= iCellCount || bHideOnly ) return;
  1133.  
  1134.   pPipeDesc->SetText( pCells[iDescCell].szCellDesc );
  1135.   pPipeDesc->AdjustSize( &fatDesc, hwPipeClient );
  1136.   SWP swp;
  1137.   WinQueryWindowPos( hwPipeFrame, &swp );
  1138.   pPipeDesc->AdjustPos( swp.x + iXOffset, swp.y + 2, 0, iWindowHeight - 4, 0 );
  1139. }
  1140.  
  1141. MRESULT EXPENTRY SwDescWinProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  1142. {
  1143.   switch ( msg )
  1144.   {
  1145.     case WM_PAINT:
  1146.       pPipeDesc->Paint( &fatDesc, hwnd );
  1147.       break;
  1148.   
  1149.     default:
  1150.       return WinDefWindowProc( hwnd, msg, mp1, mp2 );
  1151.   }
  1152.   return ( MRESULT ) FALSE;
  1153. }
  1154.  
  1155.  
  1156. void ResizeWindow( int iDiff = 0 )
  1157. {
  1158.   HideDescWindow();
  1159.   SWP Swp;
  1160.   WinQueryWindowPos( hwPipeFrame, &Swp );
  1161.   iCellSize[2] = fatCell.lMaxBaselineExt + 4;
  1162.   iWindowHeight = iCellSize[iLarge] + 6;
  1163.   iWindowWidth = 8;
  1164.   for ( int i = 0; i < iCellCount; i++ )
  1165.     iWindowWidth += pCells[i].iCellWidth;
  1166.   if ( iDiff && ! iOrientation ) Swp.x -= iDiff;
  1167.  
  1168.   WinSetWindowPos( hwPipeFrame, HWND_TOP, Swp.x, Swp.y, iWindowWidth,
  1169.     iWindowHeight, SWP_MOVE | SWP_SIZE | SWP_SHOW );
  1170.   WinInvalidateRect( hwPipeFrame, NULL, TRUE );
  1171. }
  1172.  
  1173. void ClosePipe( int iIndex )
  1174. {
  1175.   if ( pCells[iIndex].iCellType != MCT_Pipe ) return;
  1176.  
  1177.   if ( pCells[iIndex].hCellHandle )
  1178.   {
  1179.     DosDisConnectNPipe( pCells[iIndex].hCellHandle );
  1180.     DosClose( pCells[iIndex].hCellHandle );
  1181.   }
  1182.   pCells[iIndex].hCellHandle = 0;
  1183.   iPipeCount--;
  1184. }
  1185.  
  1186. void OpenPipe( int iIndex )
  1187. {
  1188.   if ( pCells[iIndex].iCellType != MCT_Pipe ) return;
  1189.  
  1190.   if ( ! pCells[iIndex].szCellDesc[0] ) strncpy( pCells[iIndex].szCellDesc,
  1191.     pCells[iIndex].szCellData1, sizeof( pCells[iIndex].szCellDesc ) - 1 );
  1192.  
  1193.   pCells[iIndex].iCellIndex = ++iCellIndexes;
  1194.   if ( ! DosCreateNPipe( pCells[iIndex].szCellData1,
  1195.     &( pCells[iIndex].hCellHandle ), NP_ACCESS_INBOUND, NP_NOWAIT |
  1196.     NP_TYPE_BYTE | NP_READMODE_BYTE | 1, iPipeBufSize, iPipeBufSize, 0L ) )
  1197.   {
  1198.     DosSetNPipeSem( pCells[iIndex].hCellHandle, ( HSEM ) hevPipeGuard,
  1199.       pCells[iIndex].iCellIndex );
  1200.     DosConnectNPipe( pCells[iIndex].hCellHandle );
  1201.     iPipeCount++;
  1202.   }
  1203.   else pCells[iIndex].hCellHandle = 0;
  1204. }
  1205.  
  1206. void ResetPipe( int iIndex )
  1207. {
  1208.   DosDisConnectNPipe( pCells[iIndex].hCellHandle );
  1209.   DosConnectNPipe( pCells[iIndex].hCellHandle );
  1210. }
  1211.  
  1212.  
  1213. void PaintCell( HPS hps, int iIndex, int bFillBackground = 0 )
  1214. {
  1215.   int iBackColor = pCells[iIndex].iCellBackColor;
  1216.   int iTextColor = pCells[iIndex].iCellTextColor;
  1217.  
  1218.   if ( pCells[iIndex].szCellData[0] )
  1219.   {
  1220.     char* pS = pCells[iIndex].szCellData +
  1221.       strlen( pCells[iIndex].szCellPrefix );
  1222.     int l1 = strlen( pS );
  1223.     for ( int i = 0; i < iColorConditionCount; i++ )
  1224.     {
  1225.       ColorCondition* pCondition = &( pCells[iIndex].Conditions[i] );
  1226.       if ( pCondition->iCondition )
  1227.       {
  1228.         int l2 = strlen( pCondition->szText );
  1229.         if ( ( pCondition->iCondition == Condition_LessThan && ( l1 < l2 ||
  1230.             ( l1 == l2 && strcmpi( pS, pCondition->szText ) < 0 ) ) ) ||
  1231.           ( pCondition->iCondition == Condition_EqualsTo && ( l1 == l2 &&
  1232.             ! strcmpi( pS, pCondition->szText ) ) ) ||
  1233.           ( pCondition->iCondition == Condition_MoreThan && ( l1 > l2 ||
  1234.             ( l1 == l2 && strcmpi( pS, pCondition->szText ) > 0 ) ) ) )
  1235.         {
  1236.           iBackColor = pCondition->iBackColor;
  1237.           iTextColor = pCondition->iTextColor;
  1238.           break;
  1239.         }
  1240.       }
  1241.     }
  1242.   }
  1243.  
  1244.   iBackColor = SB2d_ColorValue( iBackColor, iDefaultBackColor );
  1245.   iTextColor = SB2d_ColorValue( iTextColor, iDefaultTextColor );
  1246.  
  1247.   int iXOffset = 4;
  1248.   for ( int i = 0; i < iIndex; i++ ) iXOffset += pCells[i].iCellWidth;
  1249.   if ( bFillBackground ) SB2_Border( hps, iXOffset, 3, iXOffset +
  1250.     pCells[iIndex].iCellWidth - 1, 2 + iCellSize[iLarge], 0, iBackColor );
  1251.   if ( pCells[iIndex].szCellData[0] )
  1252.   {
  1253.     GpiCreateLogFont( hps, NULL, 200L, &fatCell );
  1254.     GpiSetCharSet( hps, 200L );
  1255.     CHARBUNDLE cb;
  1256.     cb.lColor = iTextColor;
  1257.     cb.usTextAlign = TA_LEFT | TA_HALF;
  1258.     GpiSetAttrs( hps, PRIM_CHAR, CBB_COLOR | CBB_TEXT_ALIGN, 0, &cb );
  1259.     POINTL pt;
  1260.     pt.x = iXOffset + 1;
  1261.     pt.y = ( iCellSize[iLarge] >> 1 ) + 3;
  1262.     RECTL rc1;
  1263.     rc1.xLeft = iXOffset + 1;
  1264.     rc1.yBottom = 4;
  1265.     rc1.xRight = rc1.xLeft + pCells[iIndex].iCellWidth - 3;
  1266.     rc1.yTop = iCellSize[iLarge] + 1;
  1267.     ULONG uOptions = CHS_CLIP | CHS_OPAQUE;
  1268.     GpiSetBackColor( hps, iBackColor );
  1269.     GpiCharStringPosAt( hps, &pt, &rc1, uOptions,
  1270.       strlen( pCells[iIndex].szCellData ), pCells[iIndex].szCellData, NULL );
  1271.     GpiDeleteSetId( hps, 200L );
  1272.   }
  1273. }
  1274.  
  1275. void PaintCell( int iIndex, int bFillBackground = 0 )
  1276. {
  1277.   if ( pCells[iIndex].iCellWidth )
  1278.   {
  1279.     HPS hps = WinGetPS( hwPipeClient );
  1280.     PaintCell( hps, iIndex, bFillBackground );
  1281.     WinReleasePS( hps );
  1282.   }
  1283. }
  1284.  
  1285.  
  1286. void AdjustPipeWidth( HPS hps, int iIndex )
  1287. {
  1288.   int iDiff = 0;
  1289.  
  1290.   if ( pCells[iIndex].szCellData[0] )
  1291.   {
  1292.     fatCell.usCodePage = GpiQueryCp( hps );
  1293.     GpiCreateLogFont( hps, NULL, 200L, &fatCell );
  1294.     GpiSetCharSet( hps, 200L );
  1295.     CHARBUNDLE cb;
  1296.     cb.usTextAlign = TA_LEFT | TA_BOTTOM;
  1297.     GpiSetAttrs( hps, PRIM_CHAR, CBB_TEXT_ALIGN, 0, &cb );
  1298.     POINTL ptl[TXTBOX_COUNT];
  1299.     GpiQueryTextBox( hps, strlen( pCells[iIndex].szCellData ),
  1300.       pCells[iIndex].szCellData, TXTBOX_COUNT, ptl );
  1301.     iDiff = ptl[TXTBOX_TOPRIGHT].x + 4;
  1302.     GpiDeleteSetId( hps, 200L );
  1303.   }
  1304.   iDiff -= pCells[iIndex].iCellWidth;
  1305.  
  1306.   if ( iDiff > 0 || ( iDiff < 0 && ! (
  1307.     ( pCells[iIndex].iCellStatus & Cell_LazyShrink ) &&
  1308.     pCells[iIndex].iCellLazyCounter ) ) )
  1309.   {
  1310.     pCells[iIndex].iCellLazyCounter = iLazySeconds;
  1311.     pCells[iIndex].iCellWidth += iDiff;
  1312.     ResizeWindow( iDiff );
  1313.   }
  1314.   else PaintCell( hps, iIndex );
  1315. }
  1316.  
  1317.  
  1318. // A procedure to save current configuration ---------------------------------
  1319. void SaveOptions( void )
  1320. {
  1321.   SWP Swp;
  1322.   if ( WinQueryWindowPos( hwPipeFrame, &Swp ) )
  1323.   {
  1324.     FILE *f = fopen( pszIniFile, "wt" );
  1325.     if ( f )
  1326.     {
  1327.       fprintf( f,
  1328.         "[%s]\n"
  1329.         "x=%i\n"
  1330.         "y=%i\n"
  1331.         "orientation=%i\n"
  1332.         "size=%i\n"
  1333.         "customsize=%i\n"
  1334.         "cornerbind=%i\n"
  1335.         "topmost=%i\n"
  1336.         "lockposition=%s\n"
  1337.         "cellcolor=%s\n"
  1338.         "textcolor=%s\n\n",
  1339.         szSysBar2Pipe, Swp.x + ( iOrientation ? 0 : iWindowWidth - 8 ), Swp.y,
  1340.         iOrientation, iLarge, iCellSize[3], iBindToCorner, iTopmost,
  1341.         pszYesNo[bLockPosition], SB2_ColorName( iDefaultBackColor ),
  1342.         SB2_ColorName( iDefaultTextColor ) );
  1343.       fprintf( f, "[%s]\n%s=", szNumberSection, szNumberDefault );
  1344.       SaveNumberOptions( f, &DefaultNumberOptions );
  1345.       fprintf( f, "\n\n" );
  1346.  
  1347.       SaveCellCfg( f );
  1348.  
  1349.       SB2_SaveFontCfg( szDescFontSection, &fatDesc, f );
  1350.       SB2_SaveFontCfg( szCellFontSection, &fatCell, f );
  1351.  
  1352.       fprintf( f, "[%s]\nweek=", szMiscSection );
  1353.       for ( int i = 0; i < iDaysOfTheWeek; i++ ) fprintf( f, "%s%c",
  1354.         szDaysOfTheWeek[i], ( i == iDaysOfTheWeek - 1 ) ? '\n' : ',' );
  1355.       fprintf( f, "month=" );
  1356.       for ( i = 0; i < iMonths; i++ )
  1357.         fprintf( f, "%s%c", szMonths[i], ( i == iMonths - 1 ) ? '\n' : ',' );
  1358.  
  1359.       fprintf( f, "\n[%s]\n", szErrorSection );
  1360.       for ( i = 0; i < iErrorCount; i++ )
  1361.         fprintf( f, "%s=%s\n", pszErrorIDs[i], pszErrors[i] );
  1362.  
  1363.       fclose( f );
  1364.     }
  1365.   }
  1366. }
  1367.  
  1368.  
  1369.  
  1370. // About dialog window procedure ---------------------------------------------
  1371. MRESULT EXPENTRY AboutDlgProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  1372. {
  1373.   if ( msg == WM_INITDLG )
  1374.   {
  1375.     WinSetDlgItemText( hwnd, D_Version, SB2_Strings( iSB2S_Version ) );
  1376.     WinSetDlgItemText( hwnd, D_Copyright, SB2_Strings( iSB2S_Copyright ) );
  1377.     WinSetDlgItemText( hwnd, D_Email, SB2_Strings( iSB2S_Email ) );
  1378.   }
  1379.   return WinDefDlgProc( hwnd, msg, mp1, mp2 );
  1380. }
  1381.  
  1382.  
  1383. static HWND hwDlgToUpdate = NULL;
  1384. void UpdateSettingsDlg( void )
  1385. {
  1386.   if ( hwDlgToUpdate )
  1387.   {
  1388.     WinSendDlgItemMsg( hwDlgToUpdate, D_Bind_Off + iBindToCorner, BM_SETCHECK,
  1389.       ( MPARAM ) 1, 0 );
  1390.     WinSendDlgItemMsg( hwDlgToUpdate, D_Grow_Left + iOrientation, BM_SETCHECK,
  1391.       ( MPARAM ) 1, 0 );
  1392.     WinSendDlgItemMsg( hwDlgToUpdate, D_Lock_Position, BM_SETCHECK,
  1393.       ( MPARAM ) bLockPosition, 0 );
  1394.   }
  1395. }
  1396.  
  1397. // Display settings dialog window procedure ----------------------------------
  1398. MRESULT EXPENTRY SettingsDlgProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  1399. {
  1400.   switch ( msg )
  1401.   {
  1402.     case WM_INITDLG:
  1403.       {
  1404.         hwDlgToUpdate = hwnd;
  1405.         WinSendDlgItemMsg( hwnd, D_Size_Size, SPBM_SETLIMITS,
  1406.           ( MPARAM ) 128, ( MPARAM ) iCellSize[3] );
  1407.         WinSendDlgItemMsg( hwnd, D_Size_Size, SPBM_SETLIMITS,
  1408.           ( MPARAM ) 128, ( MPARAM ) 16 );
  1409.         WinSendDlgItemMsg( hwnd, D_Display_None + iTopmost, BM_SETCHECK,
  1410.           ( MPARAM ) 1, 0 );
  1411.         WinSendDlgItemMsg( hwnd, D_Size_Small + iLarge, BM_SETCHECK,
  1412.           ( MPARAM ) 1, 0 );
  1413.         UpdateSettingsDlg();
  1414.       }
  1415.       break;
  1416.  
  1417.     case WM_COMMAND:
  1418.       switch ( SHORT1FROMMP( mp1 ) )
  1419.       {
  1420.         case D_Desc_Font_Settings:
  1421.           {
  1422.             fd.fAttrs = fatDesc;
  1423.             fd.clrFore = CLR_WHITE;
  1424.             fd.clrBack = CLR_DARKGRAY;
  1425.             HWND hwFontDlg = WinFontDlg( HWND_DESKTOP, hwnd, &fd );
  1426.             if ( hwFontDlg && ( fd.lReturn == DID_OK ) ) fatDesc = fd.fAttrs;
  1427.           }
  1428.           break;
  1429.         case D_Pipe_Font_Settings:
  1430.           {
  1431.             fd.fAttrs = fatCell;
  1432.             fd.clrFore = SB2_ColorValue( iDefaultTextColor );
  1433.             fd.clrBack = SB2_ColorValue( iDefaultBackColor );
  1434.             HWND hwFontDlg = WinFontDlg( HWND_DESKTOP, hwnd, &fd );
  1435.             if ( hwFontDlg && ( fd.lReturn == DID_OK ) )
  1436.             {
  1437.               fatCell = fd.fAttrs;
  1438.               HPS hps = WinGetPS( hwPipeClient );
  1439.               for ( int i = 0; i < iCellCount; i++ )
  1440.                 AdjustPipeWidth( hps, i );
  1441.               WinReleasePS( hps );
  1442.               if ( iLarge == 2 && ( iCellSize[2] !=
  1443.                 ( fatCell.lMaxBaselineExt + 4 ) ) ) ResizeWindow();
  1444.               if ( iBindToCorner ) WinPostMsg( hwPipeClient, WM_COMMAND,
  1445.                 ( MPARAM ) ( MNU_PIPE_BIND_OFF + iBindToCorner ), 0 );
  1446.             }
  1447.           }
  1448.           break;
  1449.       }
  1450.       break;
  1451.  
  1452.     case WM_CONTROL:
  1453.       switch ( SHORT1FROMMP( mp1 ) )
  1454.       {
  1455.         case D_Lock_Position:
  1456.           if ( bLockPosition != ( int ) WinSendDlgItemMsg( hwnd,
  1457.             D_Lock_Position, BM_QUERYCHECK, 0, 0 ) ) WinPostMsg( hwPipeClient,
  1458.             WM_COMMAND, ( MPARAM ) ( MNU_PIPE_LOCKPOSITION ), 0 );
  1459.           break;
  1460.         case D_Grow_Left:
  1461.         case D_Grow_Right:
  1462.           {
  1463.             int s = ( int ) WinSendDlgItemMsg( hwnd, D_Grow_Left,
  1464.               BM_QUERYCHECKINDEX, 0, 0 );
  1465.             if ( ( s & 1 ) == s ) WinPostMsg( hwPipeClient, WM_COMMAND,
  1466.               ( MPARAM ) ( MNU_PIPE_ORNT_LEFT + s ), 0 );
  1467.           }
  1468.           break;
  1469.         case D_Display_None:
  1470.         case D_Display_OnTop:
  1471.         case D_Display_Popup:
  1472.         case D_Display_Popup2:
  1473.           {
  1474.             int s = ( int ) WinSendDlgItemMsg( hwnd, D_Display_None,
  1475.               BM_QUERYCHECKINDEX, 0, 0 );
  1476.             if ( ( s & 3 ) == s ) WinPostMsg( hwPipeClient, WM_COMMAND,
  1477.               ( MPARAM ) ( MNU_PIPE_NOTOP + s ), 0 );
  1478.           }
  1479.           break;
  1480.         case D_Bind_Off:
  1481.         case D_Bind_NW:
  1482.         case D_Bind_NE:
  1483.         case D_Bind_SW:
  1484.         case D_Bind_SE:
  1485.           {
  1486.             int s = ( int ) WinSendDlgItemMsg( hwnd, D_Bind_Off,
  1487.               BM_QUERYCHECKINDEX, 0, 0 );
  1488.             if ( s >= 0 && s <= 4 ) WinPostMsg( hwPipeClient, WM_COMMAND,
  1489.               ( MPARAM ) ( MNU_PIPE_BIND_OFF + s ), 0 );
  1490.           }
  1491.           break;
  1492.         case D_Size_Small:
  1493.         case D_Size_Large:
  1494.         case D_Size_Auto:
  1495.         case D_Size_Custom:
  1496.           {
  1497.             int s = ( int ) WinSendDlgItemMsg( hwnd, D_Size_Small,
  1498.               BM_QUERYCHECKINDEX, 0, 0 );
  1499.             if ( ( s & 3 ) == s ) WinPostMsg( hwPipeClient, WM_COMMAND,
  1500.               ( MPARAM ) ( MNU_PIPE_SMALL + s ), 0 );
  1501.           }
  1502.           break;
  1503.         case D_Size_Size:
  1504.           {
  1505.             long lValue;
  1506.             WinSendDlgItemMsg( hwnd, D_Size_Size, SPBM_QUERYVALUE, &lValue, 0 );
  1507.             if ( iCellSize[3] != lValue )
  1508.             {
  1509.               iCellSize[3] = lValue;
  1510.               if ( iLarge == 3 ) WinPostMsg( hwPipeClient, WM_COMMAND,
  1511.                 ( MPARAM ) ( MNU_PIPE_CUSTOM ), 0 );
  1512.             }
  1513.           }
  1514.           break;
  1515.       }
  1516.       break;
  1517.     default:
  1518.       return WinDefDlgProc( hwnd, msg, mp1, mp2 );
  1519.   }
  1520.   return ( MRESULT ) FALSE;
  1521. }
  1522.  
  1523.  
  1524. void EnableMoveButtons( HWND hwnd, int iIndex )
  1525. {
  1526.   int bEnable = ( iCellCount > 1 );
  1527.   WinEnableControl( hwnd, D_Cell_Up, ( bEnable && iIndex ) );
  1528.   WinEnableControl( hwnd, D_Cell_Down,
  1529.     ( bEnable && ( iIndex < iCellCount - 1 ) ) );
  1530. }
  1531.  
  1532. void EnableListButtons( HWND hwnd )
  1533. {
  1534.   int bEnable = ( iCellCount > 0 );
  1535.   WinEnableControl( hwnd, D_Cell_Edit, bEnable );
  1536.   WinEnableControl( hwnd, D_Cell_Clone, bEnable );
  1537.   WinEnableControl( hwnd, D_Cell_Remove, bEnable );
  1538.   int i = ( int ) WinSendDlgItemMsg( hwnd, D_Cell_List, LM_QUERYSELECTION,
  1539.     ( MPARAM ) LIT_CURSOR, ( MPARAM ) 0 );
  1540.   EnableMoveButtons( hwnd, i );
  1541. }
  1542.  
  1543.  
  1544.  
  1545. void CleanupCell( int i )
  1546. {
  1547.   switch ( pCells[i].iCellType )
  1548.   {
  1549.     case MCT_Pipe:
  1550.       ClosePipe( i );
  1551.       break;
  1552.   }
  1553. }
  1554. void InitCell( int i )
  1555. {
  1556.   switch ( pCells[i].iCellType )
  1557.   {
  1558.     case MCT_Pipe:
  1559.       OpenPipe( i );
  1560.       break;
  1561.     case MCT_POP3:
  1562.       {
  1563.         Pop3URL* pUrl = ( Pop3URL* ) pCells[i].szCellData0;
  1564.         pUrl->pszUsername = pUrl->pszPassword = NULL;
  1565.         pUrl->pszHost = pUrl->pData;
  1566.         pUrl->iPort = 110;
  1567.         strcpy( pUrl->pData, pCells[i].szCellData1 );
  1568.         char* p1 = strrchr( pUrl->pData, '@' );
  1569.         char* p2 = strchr( pUrl->pData, ':' );
  1570.         if ( p1 )
  1571.         {
  1572.           pUrl->pszUsername = pUrl->pData;
  1573.           if ( p2 && p2 < p1 )
  1574.           {
  1575.             *p2 = 0;
  1576.             if ( p2[1] ) pUrl->pszPassword = p2 + 1;
  1577.             p2 = strchr( p1, ':' );
  1578.           }
  1579.           *p1 = 0;
  1580.         }
  1581.         if ( p1 && p1[1] ) pUrl->pszHost = p1 + 1;
  1582.         if ( p2 )
  1583.         {
  1584.           *p2 = 0;
  1585.           if ( p2[1] ) pUrl->iPort = atoi( p2 + 1 );
  1586.         }
  1587.       }
  1588.       break;
  1589.     case MCT_TrafIn:
  1590.     case MCT_TrafOut:
  1591.       memset( pCells[i].szCellData0, 0, sizeof ( pCells[i].szCellData0 ) );
  1592.       break;
  1593.   }
  1594.   if ( pCells[i].iCellWidth ) PaintCell( i, 1 );
  1595. }
  1596.  
  1597. void CopyCell( int iIndex )
  1598. {
  1599.   PSZ pszDest;
  1600.  
  1601.   if ( WinOpenClipbrd( hab ) )
  1602.   {
  1603.     if ( ! DosAllocSharedMem( ( PVOID* ) &pszDest, NULL, strlen(
  1604.       pCells[iIndex].szCellData ) + 1, PAG_WRITE | PAG_COMMIT | OBJ_GIVEABLE ) )
  1605.     {
  1606. //      pszSrc = pCells[iIndex].szCellData;
  1607.       strcpy( pszDest, pCells[iIndex].szCellData );
  1608. //      while (*pszDest++ = *pszSrc++);
  1609.       WinEmptyClipbrd( hab );
  1610.       WinSetClipbrdData( hab, ( ULONG ) pszDest, CF_TEXT, CFI_POINTER );
  1611.       WinCloseClipbrd(hab);
  1612.       DosFreeMem( pszDest );
  1613.     }
  1614.   }
  1615. }
  1616.  
  1617. void EmptyCell( int iIndex )
  1618. {
  1619.   pCells[iIndex].szCellData[0] = 0;
  1620.   int iOldWidth = pCells[iIndex].iCellWidth;
  1621.   pCells[iIndex].iCellWidth = 0;
  1622.   ResizeWindow( - iOldWidth );
  1623. }
  1624.  
  1625.  
  1626. void RemoveCell( int i )
  1627. {
  1628.   CleanupCell( i );
  1629.   if ( pCells[i].pszCellLog ) delete pCells[i].pszCellLog;
  1630.   int iOldWidth = pCells[i].iCellWidth;
  1631.   if ( --iCellCount )
  1632.   {
  1633.     if ( i < iCellCount ) memmove( &pCells[i], &pCells[i + 1],
  1634.       ( iCellCount - i ) * sizeof( CellData ) );
  1635.   }
  1636.   else
  1637.   {
  1638.     delete pCells;
  1639.     pCells = NULL;
  1640.   }
  1641.   ResizeWindow( - iOldWidth );
  1642. }
  1643.  
  1644.  
  1645. typedef struct
  1646. {
  1647.   int iIndex;
  1648.   char szText[iPipeBufSize];
  1649. } NewCellData;
  1650.  
  1651. char szLogBuffer[256] = { 0 };
  1652.  
  1653. void WriteCellLog( int iIndex, char* szBuf, short int bClearEOL = 0 )
  1654. {
  1655.   if ( pCells[iIndex].iCellStatus & Cell_Log_On )
  1656.   {
  1657.     if ( pCells[iIndex].iCellStatus & Cell_Log_Timestamping )
  1658.     {
  1659.       FormatDateTime( szLogBuffer, Cell_Check0, Cell_Check1 | Cell_Check2,
  1660.         FDT_Date | FDT_Time );
  1661.       strcat( szLogBuffer, "  " );
  1662.     }
  1663.     else szLogBuffer[0] = 0;
  1664.     strcat( szLogBuffer, szBuf );
  1665.     if ( bClearEOL )  for ( int i = strlen( szLogBuffer ) - 1; i >= 0 &&
  1666.       ( szLogBuffer[i] == '\n' || szLogBuffer[i] == '\r' ); i-- )
  1667.       szLogBuffer[i] = 0;
  1668.     strcat( szLogBuffer, "\r\n" );
  1669.     int l = strlen( szLogBuffer );
  1670.  
  1671.     if ( pCells[iIndex].iCellStatus & Cell_Log_Append &&
  1672.       pCells[iIndex].szCellLogFile[0] )
  1673.     {
  1674.       HFILE hFile = 0;
  1675.       ULONG ulAction = 0;
  1676.       if ( DosOpen( pCells[iIndex].szCellLogFile, &hFile, &ulAction,
  1677.         0, FILE_ARCHIVED | FILE_NORMAL, OPEN_ACTION_CREATE_IF_NEW |
  1678.         OPEN_ACTION_OPEN_IF_EXISTS, OPEN_FLAGS_NOINHERIT |
  1679.         OPEN_SHARE_DENYNONE | OPEN_ACCESS_WRITEONLY, 0 ) == NO_ERROR )
  1680.       {
  1681.         DosSetFilePtr( hFile, 0, FILE_END, &ulAction );
  1682.         DosWrite( hFile, ( PVOID ) szLogBuffer, l, &ulAction );
  1683.         DosClose( hFile );
  1684.       }
  1685.     }
  1686.  
  1687.     if ( pCells[iIndex].pszCellLog )
  1688.     {
  1689.       int iLogSize = pCells[iIndex].iCellLogBufferSize * 1024;
  1690.       while ( l + strlen( pCells[iIndex].pszCellLog ) >= iLogSize )
  1691.       {
  1692.         char *p = strchr( pCells[iIndex].pszCellLog, '\n' );
  1693.         if ( p ) strcpy( pCells[iIndex].pszCellLog, p + 1 );
  1694.         else pCells[iIndex].pszCellLog[0] = 0;
  1695.       }
  1696.       strcat( pCells[iIndex].pszCellLog, szLogBuffer );
  1697.       if ( iCellToSetup == iIndex && hwLogToUpdate ) WinSetDlgItemText(
  1698.         hwLogToUpdate, D_Log_MLE, pCells[iIndex].pszCellLog );
  1699.     }
  1700.   }
  1701. }
  1702.  
  1703.  
  1704. const int iCmdLineLength = iPipeBufSize + 256;
  1705.  
  1706. void SpawnIt( char *pszCommand, char *pszCellContent )
  1707. {
  1708.   char szCmdLine[iCmdLineLength] = { 0 };
  1709.   char szCmdBuffer[iCmdLineLength] = { 0 };
  1710.   char *p = szCmdLine, *pszCmdLine = szCmdBuffer;
  1711.   sprintf( szCmdBuffer, pszCommand, pszCellContent );
  1712.   short int bQuote = 0;
  1713.   while ( *pszCmdLine )
  1714.   {
  1715.     if ( *pszCmdLine == '\"' ) bQuote ^= 1;
  1716.     else if ( *pszCmdLine <= ' ' && ! bQuote )
  1717.     {
  1718.       *p++ = 0;
  1719.       while ( pszCmdLine[1] > 0 && pszCmdLine[1] <= ' ' ) pszCmdLine++;
  1720.     }
  1721.     else *p++ = ( *pszCmdLine > ' ' ? *pszCmdLine : ' ' );
  1722.     pszCmdLine++;
  1723.   }
  1724.   char *argv[32] = { 0 };
  1725.   p = szCmdLine;
  1726.   for ( int i = 0; i < 31 && *p; i++ )
  1727.   {
  1728.     argv[i] = p;
  1729.     p += strlen( p ) + 1;
  1730.   }
  1731.   spawnvp( P_NOWAIT, argv[0], ( char const * const * ) argv );
  1732. }
  1733.  
  1734.  
  1735. // Sets cell new text. Performs all necessary job such as
  1736. // cleaning all the ending linefeed and space characters,
  1737. // adding the prefix or applying the "when empty" message,
  1738. // writing the log, launching the "on change" application
  1739. // and updating the cell width if needed.
  1740. //
  1741. // Parameters:
  1742. //   iIndex - cell index
  1743. //        s - new text
  1744. void SetCellData( int iIndex, char *s )
  1745. {
  1746.   static char szBuf[iPipeBufSize];
  1747.  
  1748.   // text cleanup
  1749.   memset( szBuf, 0, iPipeBufSize );
  1750.   if ( s && s[0] )
  1751.   {
  1752.     char *p = strpbrk( s, "\r\n" );
  1753.     if ( p ) *p = 0;
  1754.     p = s + strlen( s );
  1755.     do *p = 0;
  1756.     while ( --p > s && ( *p == '\r' || *p == '\n' || *p == ' ' ) );
  1757.  
  1758.     if ( s[0] )
  1759.     {
  1760.       if ( pCells[iIndex].szCellPrefix[0] )
  1761.         strcpy( szBuf, pCells[iIndex].szCellPrefix );
  1762.       strcat( szBuf, s );
  1763.  
  1764.       WriteCellLog( iIndex, szBuf );
  1765.     }
  1766.   }
  1767.   short int bNotEmpty = 0;
  1768.  
  1769.   // dealing with the empty message
  1770.   if ( szBuf[0] == 0 && pCells[iIndex].szCellEmpty[0] )
  1771.   {
  1772.     strcpy( szBuf, pCells[iIndex].szCellPrefix );
  1773.     strcat( szBuf, pCells[iIndex].szCellEmpty );
  1774.   }
  1775.   else bNotEmpty = 1;
  1776.  
  1777.   // actions if updated
  1778.   if ( strcmp( pCells[iIndex].szCellData, szBuf ) &&
  1779.     ( pCells[iIndex].iCellStatus & Cell_Enabled ) )
  1780.   {
  1781.     strcpy( pCells[iIndex].szCellData, szBuf );
  1782.     if ( bNotEmpty && szBuf[0] && pCells[iIndex].szCellChangeApp[0] &&
  1783.       ( pCells[iIndex].iCellStatus & Cell_Change_App ) )
  1784.       SpawnIt( pCells[iIndex].szCellChangeApp, pCells[iIndex].szCellData );
  1785. //      spawnlp( P_NOWAIT, pCells[iIndex].szCellChangeApp,
  1786. //        pCells[iIndex].szCellChangeApp, NULL );
  1787.  
  1788.     HPS hps = WinGetPS( hwPipeClient );
  1789.     AdjustPipeWidth( hps, iIndex );
  1790.     WinReleasePS( hps );
  1791.     if ( pCells[iIndex].iCellType == MCT_Pipe &&
  1792.       ( pCells[iIndex].iCellStatus & Cell_Expire ) )
  1793.       pCells[iIndex].iCellCounter = pCells[iIndex].iCellSeconds + 1;
  1794.   }
  1795. }
  1796.  
  1797.  
  1798.  
  1799. static CellData TempCell;
  1800. static CellData* pCellToSetup = &TempCell;
  1801.  
  1802. void UpdateCell( CellData* pCell )
  1803. {
  1804.   if ( pCell != &TempCell && pCell->iCellStatus & Cell_Enabled &&
  1805.     pCell->iCellType != MCT_Pipe ) pCells->iCellCounter = 1;
  1806. }
  1807.  
  1808.  
  1809. // Number display options dialog window procedure ----------------------------
  1810. MRESULT EXPENTRY NumberDlgProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  1811. {
  1812.   switch ( msg )
  1813.   {
  1814.     case WM_INITDLG:
  1815.       {
  1816.         WinSetDlgItemText( hwnd, D_Number_GbName,
  1817.           pCurrentOptionsSet->szGbName );
  1818.         WinSetDlgItemText( hwnd, D_Number_MbName,
  1819.           pCurrentOptionsSet->szMbName );
  1820.         WinSetDlgItemText( hwnd, D_Number_KbName,
  1821.           pCurrentOptionsSet->szKbName );
  1822.         WinSetDlgItemText( hwnd, D_Number_bName, pCurrentOptionsSet->szbName );
  1823.  
  1824.         WinSetDlgItemShort( hwnd, D_Number_GbLimit,
  1825.           pCurrentOptionsSet->iGbLimit, 0 );
  1826.         WinSetDlgItemShort( hwnd, D_Number_MbLimit,
  1827.           pCurrentOptionsSet->iMbLimit, 0 );
  1828.         WinSetDlgItemShort( hwnd, D_Number_KbLimit,
  1829.           pCurrentOptionsSet->iKbLimit, 0 );
  1830.  
  1831.         WinCheckButton( hwnd, D_Number_Gb,
  1832.           (pCurrentOptionsSet->bUseOptions & NO_UseGb) != 0 );
  1833.         WinCheckButton( hwnd, D_Number_Mb,
  1834.           (pCurrentOptionsSet->bUseOptions & NO_UseMb) != 0 );
  1835.         WinCheckButton( hwnd, D_Number_Kb,
  1836.           (pCurrentOptionsSet->bUseOptions & NO_UseKb) != 0 );
  1837.         WinCheckButton( hwnd, D_Number_b,
  1838.           (pCurrentOptionsSet->bUseOptions & NO_Useb) != 0 );
  1839.         if ( pCurrentOptionsSet != &DefaultNumberOptions )
  1840.         {
  1841.           HWND hwControl = WinWindowFromID( hwnd, D_Number_Default );
  1842.           if ( hwControl )
  1843.             WinSetWindowPos( hwControl, 0, 0, 0, 0, 0, SWP_SHOW );
  1844.           WinCheckButton( hwnd, D_Number_Default,
  1845.             !(pCurrentOptionsSet->bUseOptions & NO_UseOwn) );
  1846.           for ( int i = D_Number_bName; i < D_Number_Default; i++ )
  1847.             WinEnableControl( hwnd, i,
  1848.               (pCurrentOptionsSet->bUseOptions & NO_UseOwn) != 0 );
  1849.         }
  1850.       }
  1851.       break;
  1852.  
  1853.     case WM_CONTROL:
  1854.       switch ( SHORT2FROMMP( mp1 ) )
  1855.       {
  1856.         case EN_CHANGE:
  1857.           switch ( SHORT1FROMMP( mp1 ) )
  1858.           {
  1859.             case D_Number_GbName:
  1860.               WinQueryDlgItemText( hwnd, D_Number_GbName,
  1861.                 sizeof( pCurrentOptionsSet->szGbName ) - 1,
  1862.                 pCurrentOptionsSet->szGbName );
  1863.               break;
  1864.             case D_Number_MbName:
  1865.               WinQueryDlgItemText( hwnd, D_Number_MbName,
  1866.                 sizeof( pCurrentOptionsSet->szMbName ) - 1,
  1867.                 pCurrentOptionsSet->szMbName );
  1868.               break;
  1869.             case D_Number_KbName:
  1870.               WinQueryDlgItemText( hwnd, D_Number_KbName,
  1871.                 sizeof( pCurrentOptionsSet->szKbName ) - 1,
  1872.                 pCurrentOptionsSet->szKbName );
  1873.               break;
  1874.             case D_Number_bName:
  1875.               WinQueryDlgItemText( hwnd, D_Number_bName,
  1876.                 sizeof( pCurrentOptionsSet->szbName ) - 1,
  1877.                 pCurrentOptionsSet->szbName );
  1878.               break;
  1879.             case D_Number_GbLimit:
  1880.               WinQueryDlgItemShort( hwnd, D_Number_GbLimit,
  1881.                 ( short* ) &( pCurrentOptionsSet->iGbLimit ), 0 );
  1882.               break;
  1883.             case D_Number_MbLimit:
  1884.               WinQueryDlgItemShort( hwnd, D_Number_MbLimit,
  1885.                 ( short* ) &( pCurrentOptionsSet->iMbLimit ), 0 );
  1886.               break;
  1887.             case D_Number_KbLimit:
  1888.               WinQueryDlgItemShort( hwnd, D_Number_KbLimit,
  1889.                 ( short* ) &( pCurrentOptionsSet->iKbLimit ), 0 );
  1890.               break;
  1891.           }
  1892.           break;
  1893.  
  1894.         case BN_CLICKED:
  1895.           {
  1896.             int bResult =
  1897.               ( WinQueryButtonCheckstate( hwnd, SHORT1FROMMP( mp1 ) ) != 0 );
  1898.             int bMask = 0;
  1899.             switch ( SHORT1FROMMP( mp1 ) )
  1900.             {
  1901.               case D_Number_Gb:
  1902.                 bMask = NO_UseGb;
  1903.                 break;
  1904.               case D_Number_Mb:
  1905.                 bMask = NO_UseMb;
  1906.                 break;
  1907.               case D_Number_Kb:
  1908.                 bMask = NO_UseKb;
  1909.                 break;
  1910.               case D_Number_b:
  1911.                 bMask = NO_Useb;
  1912.                 break;
  1913.               case D_Number_Default:
  1914.                 {
  1915.                   bMask = NO_UseOwn;
  1916.                   bResult = ! bResult;
  1917.                   for ( int i = D_Number_bName; i < D_Number_Default; i++ )
  1918.                     WinEnableControl( hwnd, i, bResult );
  1919.                 }
  1920.                 break;
  1921.             }
  1922.             pCurrentOptionsSet->bUseOptions &= ~bMask;
  1923.             if ( bResult ) pCurrentOptionsSet->bUseOptions |= bMask;
  1924.           }
  1925.           break;
  1926.       }
  1927.       break;
  1928.  
  1929.     default:
  1930.       return WinDefDlgProc( hwnd, msg, mp1, mp2 );
  1931.   }
  1932.   return ( MRESULT ) FALSE;
  1933. }
  1934.  
  1935.  
  1936. // Default colour setup dialog window procedure -------------------------------
  1937. MRESULT EXPENTRY DefColourDlgProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  1938. {
  1939.   switch ( msg )
  1940.   {
  1941.     case WM_INITDLG:
  1942.       {
  1943.         for ( int i = D_Custom_ColorG; i < D_Custom_Color_Last; i++ )
  1944.         {
  1945.           HWND hwControl = WinWindowFromID( hwnd, i );
  1946.           if ( hwControl )
  1947.             WinSetWindowPos( hwControl, 0, 0, 0, 0, 0, SWP_HIDE );
  1948.         }
  1949.         SB2_FillColorList( hwnd, D_Text_Default, iDefaultTextColor );
  1950.         SB2_FillColorList( hwnd, D_Back_Default, iDefaultBackColor );
  1951.       }
  1952.       break;
  1953.  
  1954.     case WM_CONTROL:
  1955.       switch ( SHORT1FROMMP( mp1 ) )
  1956.       {
  1957.         case D_Text_Default:
  1958.           if ( SHORT2FROMMP( mp1 ) == LN_SELECT )
  1959.           {
  1960.             iDefaultTextColor = ( int ) WinSendDlgItemMsg( hwnd, D_Text_Default,
  1961.               LM_QUERYSELECTION, ( MPARAM ) LIT_CURSOR, ( MPARAM ) 0 );
  1962.             WinInvalidateRect( hwPipeFrame, NULL, TRUE );
  1963.           }
  1964.           break;
  1965.         case D_Back_Default:
  1966.           if ( SHORT2FROMMP( mp1 ) == LN_SELECT )
  1967.           {
  1968.             iDefaultBackColor = ( int ) WinSendDlgItemMsg( hwnd, D_Back_Default,
  1969.               LM_QUERYSELECTION, ( MPARAM ) LIT_CURSOR, ( MPARAM ) 0 );
  1970.             WinInvalidateRect( hwPipeFrame, NULL, TRUE );
  1971.           }
  1972.           break;
  1973.       }
  1974.       break;
  1975.  
  1976.     default:
  1977.       return WinDefDlgProc( hwnd, msg, mp1, mp2 );
  1978.   }
  1979.   return ( MRESULT ) FALSE;
  1980. }
  1981.  
  1982.  
  1983. // Cell colour setup dialog window procedure ----------------------------------
  1984. MRESULT EXPENTRY ColourDlgProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  1985. {
  1986.   static short int bOperational = 0;
  1987.   switch ( msg )
  1988.   {
  1989.     case WM_INITDLG:
  1990.       {
  1991.         bOperational = 0;
  1992.         SB2d_FillColorList( hwnd, D_Text_Default, pCellToSetup->iCellTextColor );
  1993.         SB2d_FillColorList( hwnd, D_Back_Default, pCellToSetup->iCellBackColor );
  1994.         for ( int i = 0; i < iColorConditionCount; i++ )
  1995.         {
  1996.           WinSendDlgItemMsg( hwnd, D_Color_Condition1 + ( i << 2 ),
  1997.             SPBM_SETARRAY, ( MPARAM ) pszConditionTitles, ( MPARAM ) 4 );
  1998.           WinSendDlgItemMsg( hwnd, D_Color_Condition1 + ( i << 2 ),
  1999.             SPBM_SETCURRENTVALUE,
  2000.             ( MPARAM ) ( pCellToSetup->Conditions[i].iCondition ), 0 );
  2001.           WinSetDlgItemText( hwnd, D_Color_Text1 + ( i << 2 ),
  2002.             pCellToSetup->Conditions[i].szText );
  2003.           WinSendDlgItemMsg( hwnd, D_Color_Text1 + ( i << 2 ),
  2004.             EM_SETTEXTLIMIT, MPFROMSHORT( 31 ), 0 );
  2005.           SB2d_FillColorList( hwnd, D_Text_Color1 + ( i << 2 ),
  2006.             pCellToSetup->Conditions[i].iTextColor );
  2007.           SB2d_FillColorList( hwnd, D_Back_Color1 + ( i << 2 ),
  2008.             pCellToSetup->Conditions[i].iBackColor );
  2009.         }
  2010.         bOperational = 1;
  2011.       }
  2012.       break;
  2013.  
  2014.     case WM_CONTROL:
  2015.       {
  2016.         short int bInvalidate = 0;
  2017.         USHORT usControl = SHORT1FROMMP( mp1 );
  2018.         switch ( usControl )
  2019.         {
  2020.           case D_Text_Default:
  2021.             if ( SHORT2FROMMP( mp1 ) == LN_SELECT )
  2022.             {
  2023.               pCellToSetup->iCellTextColor =
  2024.                 ( int ) WinSendDlgItemMsg( hwnd, D_Text_Default,
  2025.                 LM_QUERYSELECTION, ( MPARAM ) LIT_CURSOR, ( MPARAM ) 0 );
  2026.               bInvalidate = 1;
  2027.             }
  2028.             break;
  2029.           case D_Back_Default:
  2030.             if ( SHORT2FROMMP( mp1 ) == LN_SELECT )
  2031.             {
  2032.               pCellToSetup->iCellBackColor =
  2033.                 ( int ) WinSendDlgItemMsg( hwnd, D_Back_Default,
  2034.                 LM_QUERYSELECTION, ( MPARAM ) LIT_CURSOR, ( MPARAM ) 0 );
  2035.               bInvalidate = 1;
  2036.             }
  2037.             break;
  2038.           case D_Color_Condition1:
  2039.           case D_Color_Condition2:
  2040.           case D_Color_Condition3:
  2041.             if ( SHORT2FROMMP( mp1 ) == SPBN_CHANGE )
  2042.             {
  2043.               int n = 0;
  2044.               WinSendDlgItemMsg( hwnd, usControl, SPBM_QUERYVALUE, &n, 0 );
  2045.               if ( bOperational )
  2046.               {
  2047.                 pCellToSetup->Conditions[( usControl -
  2048.                   D_Color_Condition1 ) >> 2].iCondition = n;
  2049.                 bInvalidate = 1;
  2050.               }
  2051.               for ( int i = 1; i < 4; i++ )
  2052.                 WinEnableControl( hwnd, usControl + i, n );
  2053.             }
  2054.             break;
  2055.           case D_Text_Color1:
  2056.           case D_Text_Color2:
  2057.           case D_Text_Color3:
  2058.             if ( SHORT2FROMMP( mp1 ) == LN_SELECT )
  2059.             {
  2060.               pCellToSetup->Conditions[( usControl - D_Text_Color1 ) >>
  2061.                 2].iTextColor = ( int ) WinSendDlgItemMsg( hwnd, usControl,
  2062.                 LM_QUERYSELECTION, ( MPARAM ) LIT_CURSOR, ( MPARAM ) 0 );
  2063.               bInvalidate = 1;
  2064.             }
  2065.             break;
  2066.           case D_Back_Color1:
  2067.           case D_Back_Color2:
  2068.           case D_Back_Color3:
  2069.             if ( SHORT2FROMMP( mp1 ) == LN_SELECT )
  2070.             {
  2071.               pCellToSetup->Conditions[( usControl - D_Back_Color1 ) >>
  2072.                 2].iBackColor = ( int ) WinSendDlgItemMsg( hwnd, usControl,
  2073.                 LM_QUERYSELECTION, ( MPARAM ) LIT_CURSOR, ( MPARAM ) 0 );
  2074.               bInvalidate = 1;
  2075.             }
  2076.             break;
  2077.           case D_Color_Text1:
  2078.           case D_Color_Text2:
  2079.           case D_Color_Text3:
  2080.             if ( SHORT2FROMMP( mp1 ) == EN_CHANGE )
  2081.             {
  2082.               WinQueryDlgItemText( hwnd, usControl,
  2083.                 sizeof( pCellToSetup->Conditions[0].szText ),
  2084.                 pCellToSetup->Conditions[( usControl - D_Color_Text1 ) >>
  2085.                 2].szText );
  2086.               bInvalidate = 1;
  2087.             }
  2088.             break;
  2089.         }
  2090.         if ( bInvalidate && ( pCellToSetup != &TempCell ) )
  2091.           WinInvalidateRect( hwPipeFrame, NULL, TRUE );
  2092.       }
  2093.       break;
  2094.  
  2095.     default:
  2096.       return WinDefDlgProc( hwnd, msg, mp1, mp2 );
  2097.   }
  2098.   return ( MRESULT ) FALSE;
  2099. }
  2100.  
  2101.  
  2102. // Hidden control setup procedure --------------------------------------------
  2103. void SetupHiddenControls( HWND hwnd, int iCellType )
  2104. {
  2105.   for ( int i = 0; i < iHiddenControlCount; i++ )
  2106.   {
  2107.     HWND hwControl = WinWindowFromID( hwnd, iHiddenControls[i] );
  2108.     if ( hwControl ) WinSetWindowPos( hwControl, 0, 0, 0, 0, 0,
  2109.       iHiddenControlSets[iCellType][i] ? SWP_SHOW : SWP_HIDE );
  2110.   }
  2111.   WinSetWindowText( WinWindowFromID( hwnd, D_Cell_NameT ),
  2112.     pszCellParamNames[iCellType] );
  2113.   for ( i = 0; i < iHiddenCheckCount; i++ )
  2114.   {
  2115.     HWND hwControl = WinWindowFromID( hwnd, D_Cell_Check0 + i );
  2116.     if ( hwControl )
  2117.     {
  2118.       WinSetWindowPos( hwControl, 0, 0, 0, 0, 0,
  2119.         pszCellCheckNames[iCellType][i] ? SWP_SHOW : SWP_HIDE );
  2120.       if ( pszCellCheckNames[iCellType][i] )
  2121.         WinSetWindowText( hwControl, pszCellCheckNames[iCellType][i] );
  2122.     }
  2123.   }
  2124. }
  2125.  
  2126.  
  2127. // Cell setup dialog window procedure ----------------------------------------
  2128. MRESULT EXPENTRY CellSetupDlgProc( HWND hwnd, ULONG msg, MPARAM mp1,
  2129.   MPARAM mp2 )
  2130. {
  2131.   static ULONG ulDiskCurr;
  2132.   static ULONG ulDiskMap;
  2133.   static int iDriveCount;
  2134.   static char szDrive[10];
  2135.   switch ( msg )
  2136.   {
  2137.     case WM_INITDLG:
  2138.       {
  2139. //        SB2_FillColorList( hwnd, D_Cell_Color );
  2140.         for ( int i = 0; i < iCellTypeCount; i++ )
  2141.           WinSendDlgItemMsg( hwnd, D_Cell_Type, LM_INSERTITEM, ( MPARAM )
  2142.             LIT_END, MPFROMP( pszCellTypes1[i] ) );
  2143.         WinSendDlgItemMsg( hwnd, D_Cell_Type, LM_SELECTITEM,
  2144.           ( MPARAM ) pCellToSetup->iCellType, ( MPARAM ) 1 );
  2145.         WinSendDlgItemMsg( hwnd, D_Cell_Desc, EM_SETTEXTLIMIT,
  2146.           ( MPARAM ) sizeof( pCellToSetup->szCellDesc ), 0 );
  2147.         WinSendDlgItemMsg( hwnd, D_Cell_Prefix, EM_SETTEXTLIMIT,
  2148.           ( MPARAM ) sizeof( pCellToSetup->szCellPrefix ), 0 );
  2149.         WinSendDlgItemMsg( hwnd, D_Cell_Empty, EM_SETTEXTLIMIT,
  2150.           ( MPARAM ) sizeof( pCellToSetup->szCellEmpty ), 0 );
  2151.         WinSendDlgItemMsg( hwnd, D_Cell_Name, EM_SETTEXTLIMIT,
  2152.           ( MPARAM ) 255, 0 );
  2153.         WinSendDlgItemMsg( hwnd, D_Cell_Seconds, SPBM_SETLIMITS,
  2154.           ( MPARAM ) 9999, ( MPARAM ) pCellToSetup->iCellSeconds );
  2155.         WinSendDlgItemMsg( hwnd, D_Cell_Seconds, SPBM_SETLIMITS,
  2156.           ( MPARAM ) 9999, ( MPARAM ) 1 );
  2157.         WinSetDlgItemText( hwnd, D_Cell_Name, pCellToSetup->szCellData1 );
  2158.         WinCheckButton( hwnd, D_Cell_Enable,
  2159.           ( pCellToSetup->iCellStatus & Cell_Enabled ) == Cell_Enabled );
  2160.         WinCheckButton( hwnd, D_Cell_Check0,
  2161.           ( pCellToSetup->iCellStatus & Cell_Check0 ) == Cell_Check0 );
  2162.         WinCheckButton( hwnd, D_Cell_Check1,
  2163.           ( pCellToSetup->iCellStatus & Cell_Check1 ) == Cell_Check1 );
  2164.         WinCheckButton( hwnd, D_Cell_Check2,
  2165.           ( pCellToSetup->iCellStatus & Cell_Check2 ) == Cell_Check2 );
  2166.         WinCheckButton( hwnd, D_Cell_Check3,
  2167.           ( pCellToSetup->iCellStatus & Cell_Check3 ) == Cell_Check3 );
  2168.         WinCheckButton( hwnd, D_Cell_Expire,
  2169.           ( pCellToSetup->iCellStatus & Cell_Expire ) == Cell_Expire );
  2170.         WinCheckButton( hwnd, D_Cell_LazyShrink,
  2171.           ( pCellToSetup->iCellStatus & Cell_LazyShrink ) == Cell_LazyShrink );
  2172.  
  2173.         WinSetDlgItemText( hwnd, D_Cell_Desc, pCellToSetup->szCellDesc );
  2174.         WinSetDlgItemText( hwnd, D_Cell_Prefix, pCellToSetup->szCellPrefix );
  2175.         WinSetDlgItemText( hwnd, D_Cell_Empty, pCellToSetup->szCellEmpty );
  2176. //        WinSendDlgItemMsg( hwnd, D_Cell_Color, LM_SELECTITEM,
  2177. //          ( MPARAM ) pCellToSetup->iCellTextColor, ( MPARAM ) 1 );
  2178.       }
  2179.       break;
  2180.  
  2181.     case WM_COMMAND:
  2182.       {
  2183.         switch ( SHORT1FROMMP( mp1 ) )
  2184.         {
  2185.           case D_Cell_BrowseFile:
  2186.             {
  2187.               HWND hwDlg;
  2188.               FILEDLG fild;
  2189.               char *pszTitle = "Select file to monitor";
  2190.  
  2191.               memset( &fild, 0, sizeof ( FILEDLG ) );
  2192.               fild.cbSize = sizeof ( FILEDLG );
  2193.               fild.fl = FDS_CENTER | FDS_OPEN_DIALOG;
  2194.               fild.pszTitle = pszTitle;
  2195.               WinQueryDlgItemText( hwnd, D_Cell_Name,
  2196.                 sizeof( fild.szFullFile ), fild.szFullFile );
  2197.               hwDlg = WinFileDlg( HWND_DESKTOP, hwnd, &fild );
  2198.               if ( hwDlg && ( fild.lReturn == DID_OK ) ) WinSetDlgItemText(
  2199.                 hwnd, D_Cell_Name, fild.szFullFile );
  2200.               if ( pCellToSetup->iCellType == MCT_FileSize )
  2201.               {
  2202.                 char *p = strrchr( fild.szFullFile, '\\' );
  2203.                 if ( ! p ) p = fild.szFullFile;
  2204.                 else p++;
  2205.                 WinSetDlgItemText( hwnd, D_Cell_Desc, p );
  2206.                 WinSetDlgItemText( hwnd, D_Cell_Prefix, p );
  2207.               }
  2208.             }
  2209.             break;
  2210.         }
  2211.       }
  2212.       break;
  2213.  
  2214.     case WM_CONTROL:
  2215.       switch ( SHORT1FROMMP( mp1 ) )
  2216.       {
  2217.         case D_Cell_Type:
  2218.           if ( SHORT2FROMMP( mp1 ) == LN_SELECT )
  2219.           {
  2220.             int i = ( int ) WinSendDlgItemMsg( hwnd, D_Cell_Type,
  2221.               LM_QUERYSELECTION, ( MPARAM ) LIT_CURSOR, ( MPARAM ) 0 );
  2222.             char *pszNewDescValue = pszCellDescs[i];
  2223.             char *pszNewPrefixValue = pszCellPrefixes[i];
  2224.             char *pszNewEmptyValue = "";
  2225.             if ( pCellToSetup->iCellType != i )
  2226.             {
  2227.               if ( iCellToSetup > -1 ) CleanupCell( iCellToSetup );
  2228.               pCellToSetup->iCellType = i;
  2229.               if ( iCellToSetup > -1 ) InitCell( iCellToSetup );
  2230.  
  2231.               switch ( i )
  2232.               {
  2233.                 case MCT_Power:
  2234.                   pszNewEmptyValue = "APM Error";
  2235.                   break;
  2236.                 case MCT_FreeSpace:
  2237.                   sprintf( szDrive, "%s%c:", pszNewDescValue,
  2238.                     pCellToSetup->szCellData1[0] + 'A' - '0' );
  2239.                   pszNewDescValue = szDrive;
  2240.                   pszNewPrefixValue = szDrive + 6;
  2241.                   break;
  2242.                 case MCT_FileSize:
  2243.                   pszNewEmptyValue = "No such file(s)";
  2244.                   break;
  2245.                 case MCT_POP3:
  2246.                   pszNewEmptyValue = "no mail";
  2247.                   break;
  2248.               }
  2249. //              if ( i == MCT_Pipe && pCellToSetup->szCellData1[0] < ' ' )
  2250. //                WinSetDlgItemText( hwnd, D_Cell_Name, "\\PIPE\\MyPipe" );
  2251.               if ( i > MCT_Pipe )
  2252.               {
  2253.                 pCellToSetup->iCellType = MCT_Pipe;
  2254.                 WinSetDlgItemText( hwnd, D_Cell_Name,
  2255.                   pszCustomPipes[i - MCT_Pipe - 1] );
  2256.                 i = MCT_Pipe;
  2257.               }
  2258.               if ( pszNewDescValue )
  2259.                 WinSetDlgItemText( hwnd, D_Cell_Desc, pszNewDescValue );
  2260.               if ( pszNewPrefixValue )
  2261.                 WinSetDlgItemText( hwnd, D_Cell_Prefix, pszNewPrefixValue );
  2262.               if ( pszNewEmptyValue )
  2263.                 WinSetDlgItemText( hwnd, D_Cell_Empty, pszNewEmptyValue );
  2264.             }
  2265.             SetupHiddenControls( hwnd, i );
  2266.             if ( i >= MCT_TCPDLLs0 && i <= MCT_TCPDLLs1 && ! hmSo32DLL )
  2267.             {
  2268.               WinCheckButton( hwnd, D_Cell_Enable, 0 );
  2269.               WinEnableControl( hwnd, D_Cell_Enable, 0 );
  2270.             }
  2271.             else WinEnableControl( hwnd, D_Cell_Enable, 1 );
  2272.             WinSendDlgItemMsg( hwnd, D_Cell_Choice, LM_DELETEALL, 0, 0 );
  2273.             switch ( i )
  2274.             {
  2275.               case MCT_TrafIn:
  2276.               case MCT_TrafOut:
  2277.                 if ( hmSo32DLL )
  2278.                 {
  2279.                   struct ifmib *pIfmib = new struct ifmib[1];
  2280.                   if ( pIfmib )
  2281.                   {
  2282.                     int iSocket = Socket( PF_INET, SOCK_STREAM, 0 );
  2283.                     if ( iSocket != -1 )
  2284.                     {
  2285.                       memset( pIfmib, 0, sizeof ( struct ifmib ) );
  2286.                       SoIOCtl( iSocket, SIOSTATIF, ( caddr_t ) pIfmib,
  2287.                         sizeof ( struct ifmib ) );
  2288.                       int n = 0;
  2289.                       for ( int i=0, j=0; i < IFMIB_ENTRIES; i++ )
  2290.                         if( pIfmib->iftable[i].iftDescr[0] ) {
  2291.                           char Item[256];
  2292.                           sprintf(Item,"%02d: %s",pIfmib->iftable[i].iftIndex,pIfmib->iftable[i].iftDescr);
  2293.                           WinSendDlgItemMsg( hwnd, D_Cell_Choice, LM_INSERTITEM,
  2294.                             ( MPARAM ) LIT_END, MPFROMP( Item ) );
  2295.                           if ( pIfmib->iftable[i].iftIndex == *(int*) pCellToSetup->szCellData1 )
  2296.                               n = j;
  2297.                           j++;
  2298.                         }
  2299.                       SoClose( iSocket );
  2300.                       WinSendDlgItemMsg( hwnd, D_Cell_Choice, LM_SELECTITEM,
  2301.                         ( MPARAM ) n, ( MPARAM ) 1 );
  2302.                     }
  2303.                     delete[] pIfmib;
  2304.                   }
  2305.                 }
  2306.                 break;
  2307.               case MCT_FreeSpace:
  2308.                 {
  2309.                   szDrive[1] = ':';
  2310.                   szDrive[2] = 0;
  2311.                   iDriveCount = 0;
  2312.                   DosQueryCurrentDisk( &ulDiskCurr, &ulDiskMap );
  2313.                   ULONG ulDiskMap2 = ulDiskMap;
  2314.                   int n = 0;
  2315.                   for ( i = 0; i < 26; i++ )
  2316.                   {
  2317.                     if ( ulDiskMap2 & 1 )
  2318.                     {
  2319.                       szDrive[0] = 'A' + i;
  2320.                       WinSendDlgItemMsg( hwnd, D_Cell_Choice, LM_INSERTITEM,
  2321.                         ( MPARAM ) LIT_END, MPFROMP( szDrive ) );
  2322.                       if ( n < pCellToSetup->szCellData1[0] - '0' ) n++;
  2323.                       iDriveCount++;
  2324.                     }
  2325.                     ulDiskMap2 >>= 1;
  2326.                   }
  2327.                   WinSendDlgItemMsg( hwnd, D_Cell_Choice, LM_SELECTITEM,
  2328.                     ( MPARAM ) ( n < iDriveCount ? n : 0 ), ( MPARAM ) 1 );
  2329.                 }
  2330.                 break;
  2331.             }
  2332.           }
  2333.           break;
  2334.         case D_Cell_Choice:
  2335.           if ( SHORT2FROMMP( mp1 ) == LN_SELECT )
  2336.           {
  2337.             int n = ( int ) WinSendDlgItemMsg( hwnd, D_Cell_Choice,
  2338.               LM_QUERYSELECTION, ( MPARAM ) LIT_CURSOR, ( MPARAM ) 0 );
  2339.             switch ( pCellToSetup->iCellType )
  2340.             {
  2341.               case MCT_FreeSpace:
  2342.                 {
  2343.                   pCellToSetup->szCellData1[0] = '0' - 1;
  2344.                   ULONG ulDiskMap2 = ulDiskMap;;
  2345.                   for ( int i = 0; i <= n; ulDiskMap2 >>= 1 )
  2346.                   {
  2347.                     if ( ulDiskMap2 & 1 ) n--;
  2348.                     pCellToSetup->szCellData1[0]++;
  2349.                   }
  2350.                   sprintf( szDrive, "Drive %c:", pCellToSetup->szCellData1[0] +
  2351.                     'A' - '0' );
  2352.                   WinSetDlgItemText( hwnd, D_Cell_Desc, szDrive );
  2353.                   WinSetDlgItemText( hwnd, D_Cell_Prefix, szDrive + 6 );
  2354.                 }
  2355.                 break;
  2356.               case MCT_TrafIn:
  2357.               case MCT_TrafOut:
  2358.                   char Item[256];
  2359.                   WinSendDlgItemMsg( hwnd, D_Cell_Choice, LM_QUERYITEMTEXT,
  2360.                        MPFROM2SHORT( n, 256 ), MPFROMP( Item ) );
  2361.                   sscanf(Item,"%d",(int*)pCellToSetup->szCellData1);
  2362.                   break;
  2363.             }
  2364.           }
  2365.           break;
  2366.  
  2367.         case D_Cell_Prefix:
  2368.           if ( SHORT2FROMMP( mp1 ) == EN_CHANGE )
  2369.           {
  2370.             WinQueryDlgItemText( hwnd, D_Cell_Prefix,
  2371.               sizeof( pCellToSetup->szCellPrefix ),
  2372.               pCellToSetup->szCellPrefix );
  2373.             UpdateCell( pCellToSetup );
  2374.           }
  2375.           break;
  2376.  
  2377.         case D_Cell_Empty:
  2378.           if ( SHORT2FROMMP( mp1 ) == EN_CHANGE )
  2379.           {
  2380.             WinQueryDlgItemText( hwnd, D_Cell_Empty,
  2381.               sizeof( pCellToSetup->szCellEmpty ), pCellToSetup->szCellEmpty );
  2382.             UpdateCell( pCellToSetup );
  2383.           }
  2384.           break;
  2385.  
  2386.         case D_Cell_Name:
  2387.           if ( SHORT2FROMMP( mp1 ) == EN_CHANGE )
  2388.           {
  2389.             if ( pCellToSetup->iCellType == MCT_Pipe )
  2390.             {
  2391.               char szBuffer[sizeof( pCellToSetup->szCellData1 )];
  2392.               WinQueryDlgItemText( hwnd, D_Cell_Name,
  2393.                 sizeof( pCellToSetup->szCellData1 ), szBuffer );
  2394.               if ( strnicmp( szBuffer, "\\PIPE\\", 6 ) )
  2395.               {
  2396.                 char szBuf[sizeof( pCellToSetup->szCellData1 )];
  2397.                 strcpy( szBuf, szBuffer );
  2398.                 strcpy( szBuffer, "\\PIPE" );
  2399.                 char *p2 = &( szBuffer[5] );
  2400.                 if ( szBuf[0] != '\\' ) *p2++ = '\\';
  2401.                 strcpy( p2, szBuf );
  2402.                 WinSetDlgItemText( hwnd, D_Cell_Name, szBuffer );
  2403.                 break;
  2404.               }
  2405.             }
  2406.             if ( pCellToSetup->iCellType != MCT_FreeSpace &&
  2407.               pCellToSetup->iCellType != MCT_TrafIn &&
  2408.               pCellToSetup->iCellType != MCT_TrafOut )
  2409.             {
  2410.               if ( iCellToSetup > -1 )
  2411.               {
  2412.                 CleanupCell( iCellToSetup );
  2413.                 WinQueryDlgItemText( hwnd, D_Cell_Name,
  2414.                   sizeof( pCellToSetup->szCellData1 ),
  2415.                   pCellToSetup->szCellData1 );
  2416.                 InitCell( iCellToSetup );
  2417.                 UpdateCell( pCellToSetup );
  2418.               }
  2419.             }
  2420.           }
  2421.           break;
  2422.  
  2423.         case D_Cell_Seconds:
  2424.           if ( SHORT2FROMMP( mp1 ) == SPBN_CHANGE )
  2425.           {
  2426.             WinSendDlgItemMsg( hwnd, D_Cell_Seconds, SPBM_QUERYVALUE,
  2427.               ( short* ) &( pCellToSetup->iCellSeconds ), 0 );
  2428.             pCellToSetup->iCellCounter = pCellToSetup->iCellSeconds;
  2429.           }
  2430.           break;
  2431.  
  2432.         case D_Cell_Enable:
  2433.           if ( SHORT2FROMMP( mp1 ) == BN_CLICKED )
  2434.           {
  2435.             if ( WinQueryButtonCheckstate( hwnd, D_Cell_Enable ) )
  2436.             {
  2437.               if ( ! ( pCellToSetup->iCellStatus & Cell_Enabled ) &&
  2438.                 iCellToSetup > -1 ) InitCell( iCellToSetup );
  2439.               pCellToSetup->iCellStatus |= Cell_Enabled;
  2440.             }
  2441.             else
  2442.             {
  2443.               if ( pCellToSetup->iCellStatus & Cell_Enabled &&
  2444.                 iCellToSetup > -1 ) CleanupCell( iCellToSetup );
  2445.               pCellToSetup->iCellStatus &= ~Cell_Enabled;
  2446.             }
  2447.           }
  2448.           break;
  2449.  
  2450.         case D_Cell_Expire:
  2451.           if ( SHORT2FROMMP( mp1 ) == BN_CLICKED )
  2452.           {
  2453.             if ( WinQueryButtonCheckstate( hwnd, D_Cell_Expire ) )
  2454.               pCellToSetup->iCellStatus |= Cell_Expire;
  2455.             else pCellToSetup->iCellStatus &= ~Cell_Expire;
  2456.           }
  2457.           break;
  2458.  
  2459.         case D_Cell_LazyShrink:
  2460.           if ( SHORT2FROMMP( mp1 ) == BN_CLICKED )
  2461.           {
  2462.             if ( WinQueryButtonCheckstate( hwnd, D_Cell_LazyShrink ) )
  2463.               pCellToSetup->iCellStatus |= Cell_LazyShrink;
  2464.             else pCellToSetup->iCellStatus &= ~Cell_LazyShrink;
  2465.           }
  2466.           break;
  2467.  
  2468.         case D_Cell_Check0:
  2469.           if ( SHORT2FROMMP( mp1 ) == BN_CLICKED )
  2470.           {
  2471.             if ( WinQueryButtonCheckstate( hwnd, D_Cell_Check0 ) )
  2472.               pCellToSetup->iCellStatus |= Cell_Check0;
  2473.             else pCellToSetup->iCellStatus &= ~Cell_Check0;
  2474.             UpdateCell( pCellToSetup );
  2475.           }
  2476.           break;
  2477.  
  2478.         case D_Cell_Check1:
  2479.           if ( SHORT2FROMMP( mp1 ) == BN_CLICKED )
  2480.           {
  2481.             if ( WinQueryButtonCheckstate( hwnd, D_Cell_Check1 ) )
  2482.               pCellToSetup->iCellStatus |= Cell_Check1;
  2483.             else pCellToSetup->iCellStatus &= ~Cell_Check1;
  2484.             UpdateCell( pCellToSetup );
  2485.           }
  2486.           break;
  2487.  
  2488.         case D_Cell_Check2:
  2489.           if ( SHORT2FROMMP( mp1 ) == BN_CLICKED )
  2490.           {
  2491.             if ( WinQueryButtonCheckstate( hwnd, D_Cell_Check2 ) )
  2492.               pCellToSetup->iCellStatus |= Cell_Check2;
  2493.             else pCellToSetup->iCellStatus &= ~Cell_Check2;
  2494.             UpdateCell( pCellToSetup );
  2495.           }
  2496.           break;
  2497.  
  2498.         case D_Cell_Check3:
  2499.           if ( SHORT2FROMMP( mp1 ) == BN_CLICKED )
  2500.           {
  2501.             if ( WinQueryButtonCheckstate( hwnd, D_Cell_Check3 ) )
  2502.               pCellToSetup->iCellStatus |= Cell_Check3;
  2503.             else pCellToSetup->iCellStatus &= ~Cell_Check3;
  2504.             UpdateCell( pCellToSetup );
  2505.           }
  2506.           break;
  2507.       }
  2508.       break;
  2509.  
  2510.     case WM_DESTROY:
  2511.       WinQueryDlgItemText( hwnd, D_Cell_Desc,
  2512.         sizeof( pCellToSetup->szCellDesc ), pCellToSetup->szCellDesc );
  2513.       if ( pCellToSetup->iCellType != MCT_FreeSpace &&
  2514.         pCellToSetup->iCellType != MCT_TrafIn &&
  2515.         pCellToSetup->iCellType != MCT_TrafOut )
  2516.          WinQueryDlgItemText( hwnd, D_Cell_Name,
  2517.            sizeof( pCellToSetup->szCellData1 ), pCellToSetup->szCellData1 );
  2518.     default:
  2519.       return WinDefDlgProc( hwnd, msg, mp1, mp2 );
  2520.   }
  2521.   return ( MRESULT ) FALSE;
  2522. }
  2523.  
  2524.  
  2525. // Cell application setup dialog window procedure ----------------------------
  2526. MRESULT EXPENTRY CellAppSetupDlgProc( HWND hwnd, ULONG msg, MPARAM mp1,
  2527.   MPARAM mp2 )
  2528. {
  2529.   switch ( msg )
  2530.   {
  2531.     case WM_INITDLG:
  2532.       {
  2533.         WinCheckButton( hwnd, D_App_IncomeX,
  2534.           ( pCellToSetup->iCellStatus & Cell_Change_App ) == Cell_Change_App );
  2535.         WinCheckButton( hwnd, D_App_DblclickX,
  2536.           ( pCellToSetup->iCellStatus & Cell_Click_App ) == Cell_Click_App );
  2537.         WinSendDlgItemMsg( hwnd, D_App_IncomeTxt, EM_SETTEXTLIMIT,
  2538.           ( MPARAM ) sizeof( pCellToSetup->szCellChangeApp ), 0 );
  2539.         WinSendDlgItemMsg( hwnd, D_App_DblclickTxt, EM_SETTEXTLIMIT,
  2540.           ( MPARAM ) sizeof( pCellToSetup->szCellClickApp ), 0 );
  2541.         WinSetDlgItemText( hwnd, D_App_IncomeTxt, pCellToSetup->szCellChangeApp );
  2542.         WinSetDlgItemText( hwnd, D_App_DblclickTxt, pCellToSetup->szCellClickApp );
  2543.       }
  2544.       break;
  2545.  
  2546.     case WM_COMMAND:
  2547.       {
  2548.         switch ( SHORT1FROMMP( mp1 ) )
  2549.         {
  2550.           case D_App_IncomeBrw:
  2551.           case D_App_DblclickBrw:
  2552.             {
  2553.               HWND hwDlg;
  2554.               FILEDLG fild;
  2555.               char *pszTitle = "Select file to execute";
  2556.               int n = ( SHORT1FROMMP( mp1 ) == D_App_IncomeBrw );
  2557.  
  2558.               memset( &fild, 0, sizeof ( FILEDLG ) );
  2559.               fild.cbSize = sizeof ( FILEDLG );
  2560.               fild.fl = FDS_CENTER | FDS_OPEN_DIALOG;
  2561.               fild.pszTitle = pszTitle;
  2562.               WinQueryDlgItemText( hwnd, n ? D_App_IncomeTxt :
  2563.                 D_App_DblclickTxt, sizeof( fild.szFullFile ), fild.szFullFile );
  2564.               hwDlg = WinFileDlg( HWND_DESKTOP, hwnd, &fild );
  2565.               if ( hwDlg && ( fild.lReturn == DID_OK ) ) WinSetDlgItemText(
  2566.                 hwnd, n ? D_App_IncomeTxt : D_App_DblclickTxt,
  2567.                 fild.szFullFile );
  2568.             }
  2569.             break;
  2570.         }
  2571.       }
  2572.       break;
  2573.  
  2574.     case WM_CONTROL:
  2575.       switch ( SHORT1FROMMP( mp1 ) )
  2576.       {
  2577.         case D_App_IncomeTxt:
  2578.           if ( SHORT2FROMMP( mp1 ) == EN_CHANGE ) WinQueryDlgItemText( hwnd,
  2579.             D_App_IncomeTxt, sizeof( pCellToSetup->szCellChangeApp ),
  2580.             pCellToSetup->szCellChangeApp );
  2581.           break;
  2582.  
  2583.         case D_App_DblclickTxt:
  2584.           if ( SHORT2FROMMP( mp1 ) == EN_CHANGE ) WinQueryDlgItemText( hwnd,
  2585.             D_App_DblclickTxt, sizeof( pCellToSetup->szCellClickApp ),
  2586.             pCellToSetup->szCellClickApp );
  2587.           break;
  2588.  
  2589.         case D_App_IncomeX:
  2590.           if ( SHORT2FROMMP( mp1 ) == BN_CLICKED )
  2591.           {
  2592.             if ( WinQueryButtonCheckstate( hwnd, D_App_IncomeX ) )
  2593.               pCellToSetup->iCellStatus |= Cell_Change_App;
  2594.             else pCellToSetup->iCellStatus &= ~Cell_Change_App;
  2595.           }
  2596.           break;
  2597.  
  2598.         case D_App_DblclickX:
  2599.           if ( SHORT2FROMMP( mp1 ) == BN_CLICKED )
  2600.           {
  2601.             if ( WinQueryButtonCheckstate( hwnd, D_App_DblclickX ) )
  2602.               pCellToSetup->iCellStatus |= Cell_Click_App;
  2603.             else pCellToSetup->iCellStatus &= ~Cell_Click_App;
  2604.           }
  2605.           break;
  2606.       }
  2607.       break;
  2608.  
  2609.     default:
  2610.       return WinDefDlgProc( hwnd, msg, mp1, mp2 );
  2611.   }
  2612.   return ( MRESULT ) FALSE;
  2613. }
  2614.  
  2615.  
  2616. // Cell log setup dialog window procedure ------------------------------------
  2617. MRESULT EXPENTRY CellLogSetupDlgProc( HWND hwnd, ULONG msg, MPARAM mp1,
  2618.   MPARAM mp2 )
  2619. {
  2620.   switch ( msg )
  2621.   {
  2622.     case WM_INITDLG:
  2623.       {
  2624.         WinCheckButton( hwnd, D_Log_Enable,
  2625.           ( pCellToSetup->iCellStatus & Cell_Log_On ) == Cell_Log_On );
  2626.         WinCheckButton( hwnd, D_Log_Timestamping, ( pCellToSetup->iCellStatus &
  2627.           Cell_Log_Timestamping ) == Cell_Log_Timestamping );
  2628.         WinCheckButton( hwnd, D_Log_AppendX,
  2629.           ( pCellToSetup->iCellStatus & Cell_Log_Append ) == Cell_Log_Append );
  2630.         WinSendDlgItemMsg( hwnd, D_Log_AppendFile, EM_SETTEXTLIMIT,
  2631.           ( MPARAM ) sizeof( pCellToSetup->szCellLogFile ), 0 );
  2632.         WinSetDlgItemText( hwnd, D_Log_AppendFile, pCellToSetup->szCellLogFile );
  2633.         WinSendDlgItemMsg( hwnd, D_Log_Buffer, SPBM_SETLIMITS,
  2634.           ( MPARAM ) 64, ( MPARAM ) pCellToSetup->iCellLogBufferSize );
  2635.         WinSendDlgItemMsg( hwnd, D_Log_Buffer, SPBM_SETLIMITS,
  2636.           ( MPARAM ) 64, ( MPARAM ) 1 );
  2637.         WinSetDlgItemText( hwnd, D_Log_MLE, pCellToSetup->pszCellLog );
  2638.         hwLogToUpdate = hwnd;
  2639.       }
  2640.       break;
  2641.  
  2642.     case WM_COMMAND:
  2643.       {
  2644.         switch ( SHORT1FROMMP( mp1 ) )
  2645.         {
  2646.           case D_Log_AppendBrw:
  2647.             {
  2648.               HWND hwDlg;
  2649.               FILEDLG fild;
  2650.               char *pszTitle = "Select log file";
  2651.  
  2652.               memset( &fild, 0, sizeof ( FILEDLG ) );
  2653.               fild.cbSize = sizeof ( FILEDLG );
  2654.               fild.fl = FDS_CENTER | FDS_OPEN_DIALOG;
  2655.               fild.pszTitle = pszTitle;
  2656.               WinQueryDlgItemText( hwnd, D_Log_AppendFile,
  2657.                 sizeof( fild.szFullFile ), fild.szFullFile );
  2658.               hwDlg = WinFileDlg( HWND_DESKTOP, hwnd, &fild );
  2659.               if ( hwDlg && ( fild.lReturn == DID_OK ) ) WinSetDlgItemText(
  2660.                 hwnd, D_Log_AppendFile, fild.szFullFile );
  2661.             }
  2662.             break;
  2663.         }
  2664.       }
  2665.       break;
  2666.  
  2667.     case WM_CONTROL:
  2668.       switch ( SHORT1FROMMP( mp1 ) )
  2669.       {
  2670.         case D_Log_Enable:
  2671.           if ( SHORT2FROMMP( mp1 ) == BN_CLICKED )
  2672.           {
  2673.             if ( WinQueryButtonCheckstate( hwnd, D_Log_Enable ) )
  2674.             {
  2675.               pCellToSetup->iCellStatus |= Cell_Log_On;
  2676.               if ( pCellToSetup->pszCellLog == NULL )
  2677.               {
  2678.                 int iBufferSize = pCellToSetup->iCellLogBufferSize << 10;
  2679.                 if ( pCellToSetup->pszCellLog = new char[iBufferSize] )
  2680.                   memset( pCellToSetup->pszCellLog, 0, iBufferSize );
  2681.               }
  2682.             }
  2683.             else pCellToSetup->iCellStatus &= ~Cell_Log_On;
  2684.           }
  2685.           break;
  2686.  
  2687.         case D_Log_Timestamping:
  2688.           if ( SHORT2FROMMP( mp1 ) == BN_CLICKED )
  2689.           {
  2690.             if ( WinQueryButtonCheckstate( hwnd, D_Log_Timestamping ) )
  2691.               pCellToSetup->iCellStatus |= Cell_Log_Timestamping;
  2692.             else pCellToSetup->iCellStatus &= ~Cell_Log_Timestamping;
  2693.           }
  2694.           break;
  2695.  
  2696.         case D_Log_AppendX:
  2697.           if ( SHORT2FROMMP( mp1 ) == BN_CLICKED )
  2698.           {
  2699.             if ( WinQueryButtonCheckstate( hwnd, D_Log_AppendX ) )
  2700.               pCellToSetup->iCellStatus |= Cell_Log_Append;
  2701.             else pCellToSetup->iCellStatus &= ~Cell_Log_Append;
  2702.           }
  2703.           break;
  2704.  
  2705.         case D_Log_AppendFile:
  2706.           if ( SHORT2FROMMP( mp1 ) == EN_CHANGE ) WinQueryDlgItemText( hwnd,
  2707.             D_Log_AppendFile, sizeof( pCellToSetup->szCellLogFile ),
  2708.             pCellToSetup->szCellLogFile );
  2709.           break;
  2710.  
  2711.         case D_Log_Buffer:
  2712.           if ( SHORT2FROMMP( mp1 ) == SPBN_CHANGE )
  2713.           {
  2714.             int iBufferSize = pCellToSetup->iCellLogBufferSize;
  2715.             WinSendDlgItemMsg( hwnd, D_Log_Buffer, SPBM_QUERYVALUE,
  2716.               ( short* ) &( iBufferSize ), 0 );
  2717.             if ( iBufferSize != pCellToSetup->iCellLogBufferSize ||
  2718.               ( ( pCellToSetup->iCellStatus & Cell_Log_On ) &&
  2719.               ! pCellToSetup->pszCellLog ) )
  2720.             {
  2721.               int iNewBufferSize = iBufferSize * 1024;
  2722.               char* pBuffer = new char[iNewBufferSize];
  2723.               if ( pBuffer )
  2724.               {
  2725.                 memset( pBuffer, 0, iNewBufferSize );
  2726.                 if ( pCellToSetup->pszCellLog )
  2727.                 {
  2728.                   char* pOldBuffer = pCellToSetup->pszCellLog;
  2729.                   if ( iBufferSize < pCellToSetup->iCellLogBufferSize &&
  2730.                     strlen( pCellToSetup->pszCellLog ) > iNewBufferSize - 1 )
  2731.                   {
  2732.                     pCellToSetup->pszCellLog +=
  2733.                       strlen( pCellToSetup->pszCellLog ) - iNewBufferSize;
  2734.                     do pCellToSetup->pszCellLog++;
  2735.                     while ( pCellToSetup->pszCellLog[-1] != '\n' );
  2736.                   }
  2737.                   strcpy( pBuffer, pCellToSetup->pszCellLog );
  2738.                   pCellToSetup->pszCellLog = pBuffer;
  2739.                   delete pOldBuffer;
  2740.                 }
  2741.                 else pCellToSetup->pszCellLog = pBuffer;
  2742.               }
  2743.             }
  2744.             pCellToSetup->iCellLogBufferSize = iBufferSize;
  2745.           }
  2746.           break;
  2747.       }
  2748.       break;
  2749.  
  2750.     case WM_DESTROY:
  2751.       hwLogToUpdate = NULLHANDLE;
  2752.     default:
  2753.       return WinDefDlgProc( hwnd, msg, mp1, mp2 );
  2754.   }
  2755.   return ( MRESULT ) FALSE;
  2756. }
  2757.  
  2758.  
  2759.  
  2760. // Main properties dialog window procedure -----------------------------------
  2761. MRESULT EXPENTRY CellNotebookDlgProc( HWND hwnd, ULONG msg, MPARAM mp1,
  2762.   MPARAM mp2 )
  2763. {
  2764.   static ULONG ulFirstPageDlg = NULL;
  2765.   static ULONG ulColorsPageDlg = NULL;
  2766.   static ULONG ulNumberPageDlg = NULL;
  2767.   static ULONG ulProgramPageDlg = NULL;
  2768.   static ULONG ulLogPageDlg = NULL;
  2769.   static HWND hwFirstPageDlg = NULL;
  2770.   static HWND hwColorsPageDlg = NULL;
  2771.   static HWND hwNumberPageDlg = NULL;
  2772.   static HWND hwProgramPageDlg = NULL;
  2773.   static HWND hwLogPageDlg = NULL;
  2774.   switch ( msg )
  2775.   {
  2776.     case WM_INITDLG:
  2777.       if ( mp2 )
  2778.       {
  2779.         HWND hwControl = WinWindowFromID( hwnd, DID_OK );
  2780.         if ( hwControl ) WinSetWindowPos( hwControl, 0, 0, 0, 0, 0,
  2781.           iCellToSetup == -1 ? SWP_SHOW : SWP_HIDE );
  2782.         hwControl = WinWindowFromID( hwnd, DID_CANCEL );
  2783.         WinSetWindowText( hwControl,
  2784.           iCellToSetup == -1 ? "~Cancel" : "~Close" );
  2785.  
  2786.         WinSendDlgItemMsg( hwnd, D_Cell_Notebook, BKM_SETNOTEBOOKCOLORS,
  2787.           MPFROMLONG( SYSCLR_DIALOGBACKGROUND ),
  2788.           MPFROMLONG( BKA_BACKGROUNDPAGECOLORINDEX ) );
  2789.         HWND hwCellNotebook = WinWindowFromID( hwnd, D_Cell_Notebook );
  2790.  
  2791.         ulFirstPageDlg = SB2_AddDlgPage( hwnd, D_Cell_Notebook, "Cell",
  2792.           "General cell settings" );
  2793.         hwFirstPageDlg = WinLoadDlg( hwCellNotebook, hwCellNotebook,
  2794.           CellSetupDlgProc, ( HMODULE ) 0, D_Cell_Page1, NULL );
  2795.         WinSendDlgItemMsg( hwnd, D_Cell_Notebook, BKM_SETPAGEWINDOWHWND,
  2796.           ( MPARAM ) ulFirstPageDlg, ( MPARAM ) hwFirstPageDlg );
  2797.  
  2798.         ulColorsPageDlg = SB2_AddDlgPage( hwnd, D_Cell_Notebook, "Colors",
  2799.           "Cell color options" );
  2800.         hwColorsPageDlg = WinLoadDlg( hwCellNotebook, hwCellNotebook,
  2801.           ColourDlgProc, ( HMODULE ) 0, D_Cell_PageColors, NULL );
  2802.         WinSendDlgItemMsg( hwnd, D_Cell_Notebook, BKM_SETPAGEWINDOWHWND,
  2803.           ( MPARAM ) ulColorsPageDlg, ( MPARAM ) hwColorsPageDlg );
  2804.  
  2805.         ulNumberPageDlg = SB2_AddDlgPage( hwnd, D_Cell_Notebook, "Numbers",
  2806.           "Number display options" );
  2807.         hwNumberPageDlg = WinLoadDlg( hwCellNotebook, hwCellNotebook,
  2808.           NumberDlgProc, ( HMODULE ) 0, D_Number_Dialog, NULL );
  2809.         WinSendDlgItemMsg( hwnd, D_Cell_Notebook, BKM_SETPAGEWINDOWHWND,
  2810.           ( MPARAM ) ulNumberPageDlg, ( MPARAM ) hwNumberPageDlg );
  2811. /*
  2812.         ulNumberPageDlg = ( ULONG ) WinSendDlgItemMsg( hwnd, D_Cell_Notebook,
  2813.           BKM_INSERTPAGE, ( MPARAM ) NULL, MPFROM2SHORT( ( BKA_MINOR |
  2814.           BKA_STATUSTEXTON | BKA_AUTOPAGESIZE ), BKA_LAST ) );
  2815.         WinSendMsg( hwCellNotebook, BKM_SETSTATUSLINETEXT,
  2816.           ( MPARAM ) ulNumberPageDlg,
  2817.           MPFROMP ( "Number display options (page 2 of 2)" ) );
  2818.         hwNumberPageDlg = WinLoadDlg( hwCellNotebook, hwCellNotebook,
  2819.           NumberDlgProc, ( HMODULE ) 0, D_Number_Dialog, NULL );
  2820.         WinSendMsg( hwCellNotebook, BKM_SETPAGEWINDOWHWND,
  2821.           ( MPARAM ) ulNumberPageDlg, ( MPARAM ) hwNumberPageDlg );
  2822. */
  2823.         ulProgramPageDlg = SB2_AddDlgPage( hwnd, D_Cell_Notebook, "Programs",
  2824.           "Application settings" );
  2825.         hwProgramPageDlg = WinLoadDlg( hwCellNotebook, hwCellNotebook,
  2826.           CellAppSetupDlgProc, ( HMODULE ) 0, D_Cell_PageApp, NULL );
  2827.         WinSendDlgItemMsg( hwnd, D_Cell_Notebook, BKM_SETPAGEWINDOWHWND,
  2828.           ( MPARAM ) ulProgramPageDlg, ( MPARAM ) hwProgramPageDlg );
  2829.  
  2830.         ulLogPageDlg = SB2_AddDlgPage( hwnd, D_Cell_Notebook, "Logging",
  2831.           "Cell log settings" );
  2832.         hwLogPageDlg = WinLoadDlg( hwCellNotebook, hwCellNotebook,
  2833.           CellLogSetupDlgProc, ( HMODULE ) 0, D_Cell_PageLog, NULL );
  2834.         WinSendDlgItemMsg( hwnd, D_Cell_Notebook, BKM_SETPAGEWINDOWHWND,
  2835.           ( MPARAM ) ulLogPageDlg, ( MPARAM ) hwLogPageDlg );
  2836. /*
  2837.         ulNumberPageDlg = SB2_AddDlgPage( hwnd, D_Cell_Notebook, "Numbers",
  2838.           "Number display settings" );
  2839.         hwNumberPageDlg = WinLoadDlg( hwCellNotebook, hwCellNotebook,
  2840.           NumberDlgProc, ( HMODULE ) 0, D_Number_Dialog, NULL );
  2841.         WinSendDlgItemMsg( hwnd, D_Cell_Notebook, BKM_SETPAGEWINDOWHWND,
  2842.           ( MPARAM ) ulNumberPageDlg, ( MPARAM ) hwNumberPageDlg );
  2843. */
  2844.         WinSendDlgItemMsg( hwnd, D_Cell_Notebook, BKM_SETDIMENSIONS,
  2845.           MPFROM2SHORT ( 21, 21 ), MPFROMSHORT ( BKA_PAGEBUTTON ) );
  2846.         WinSendDlgItemMsg( hwnd, D_Cell_Notebook, BKM_SETDIMENSIONS,
  2847.           MPFROM2SHORT ( 70, 20 ), MPFROMSHORT ( BKA_MAJORTAB ) );
  2848.         WinSendDlgItemMsg( hwnd, D_Cell_Notebook, BKM_SETDIMENSIONS,
  2849.           MPFROM2SHORT ( 0, 0 ), MPFROMSHORT ( BKA_MINORTAB ) );
  2850.       }
  2851.       break;
  2852.  
  2853.     case WM_CLOSE:
  2854.       WinDestroyWindow( hwFirstPageDlg );
  2855.       WinDestroyWindow( hwColorsPageDlg );
  2856.       WinDestroyWindow( hwNumberPageDlg );
  2857.       WinDestroyWindow( hwProgramPageDlg );
  2858.       WinDestroyWindow( hwLogPageDlg );
  2859.       hwFirstPageDlg = NULL; 
  2860.       hwColorsPageDlg = NULL;
  2861.       hwNumberPageDlg = NULL;
  2862.       hwProgramPageDlg = NULL;
  2863.       hwLogPageDlg = NULL;
  2864.     default:
  2865.       return WinDefDlgProc( hwnd, msg, mp1, mp2 );
  2866.   }
  2867.   return ( MRESULT ) FALSE;
  2868. }
  2869.  
  2870.  
  2871. int EditCell( HWND hwnd, int iIndex = -1 )
  2872. {
  2873.   if ( iIndex >= 0 ) TempCell = pCells[iIndex];
  2874.  
  2875.   iCellToSetup = iIndex;
  2876.   pCellToSetup = ( iIndex == -1 ? &TempCell : &pCells[iIndex] );
  2877.   pCurrentOptionsSet = &( pCellToSetup->noCellOptions );
  2878.  
  2879.   int iResult = WinDlgBox( HWND_DESKTOP, hwnd, CellNotebookDlgProc,
  2880.     ( HMODULE ) 0, D_Cell_Setup, ( PVOID ) &DummyInit );
  2881.   iCellToSetup = -1;
  2882.   pCellToSetup = NULL;
  2883.  
  2884. /*
  2885.   if ( iResult == DID_OK )
  2886.   {
  2887.     TempCell.iCellCounter = 0;
  2888.     TempCell.hCellHandle = 0;
  2889.     if ( iIndex >= 0 )
  2890.     {
  2891.       CleanupCell( iIndex );
  2892.       strcpy( TempCell.szCellData, pCells[iIndex].szCellData );
  2893.       TempCell.iCellWidth = pCells[iIndex].iCellWidth;
  2894.       pCells[iIndex] = TempCell;
  2895.       InitCell( iIndex );
  2896.     }
  2897.     }
  2898. */
  2899.   pCurrentOptionsSet = &DefaultNumberOptions;
  2900.   return ( iResult == DID_OK );
  2901. }
  2902.  
  2903.  
  2904. // Cell settings dialog window procedure -------------------------------------
  2905. MRESULT EXPENTRY CellsDlgProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  2906. {
  2907.   switch ( msg )
  2908.   {
  2909.     case WM_INITDLG:
  2910.       {
  2911.         memset( &TempCell, 0, sizeof( TempCell ) );
  2912. //        SB2_FillColorList( hwnd, D_Cell_Color );
  2913. //        WinSendDlgItemMsg( hwnd, D_Cell_Desc, EM_SETTEXTLIMIT,
  2914. //          ( MPARAM ) sizeof( TempCell.szCellDesc ), 0 );
  2915. //        WinSendDlgItemMsg( hwnd, D_Cell_Prefix, EM_SETTEXTLIMIT,
  2916. //          ( MPARAM ) sizeof( TempCell.szCellPrefix ), 0 );
  2917. //        WinSendDlgItemMsg( hwnd, D_Cell_App, EM_SETTEXTLIMIT,
  2918. //          ( MPARAM ) sizeof( TempCell.szCellClickApp ), 0 );
  2919.         for ( int i = 0; i < iCellCount; i++ )
  2920.           WinSendDlgItemMsg( hwnd, D_Cell_List, LM_INSERTITEM,
  2921.             ( MPARAM ) LIT_END, MPFROMP( pCells[i].szCellDesc ) );
  2922.         WinSendDlgItemMsg( hwnd, D_Cell_List, LM_SELECTITEM,
  2923.           ( MPARAM ) 0, ( MPARAM ) 1 );
  2924.         EnableListButtons( hwnd );
  2925.       }
  2926.       break;
  2927.  
  2928.     case WM_COMMAND:
  2929.       {
  2930.         int i = ( int ) WinSendDlgItemMsg( hwnd, D_Cell_List,
  2931.           LM_QUERYSELECTION, ( MPARAM ) LIT_CURSOR, ( MPARAM ) 0 );
  2932.  
  2933.         switch ( SHORT1FROMMP( mp1 ) )
  2934.         {
  2935.           case D_Cell_Edit:
  2936.             if ( EditCell( hwnd, i ) ) WinSendDlgItemMsg( hwnd, D_Cell_List,
  2937.               LM_SETITEMTEXT, ( MPARAM ) i, MPFROMP( TempCell.szCellDesc ) );
  2938.             break;
  2939.  
  2940.           case D_Cell_New:
  2941.             TempCell.iCellType = 0;
  2942.             TempCell.iCellTextColor = 0;
  2943.             TempCell.iCellBackColor = 0;
  2944.             TempCell.iCellSeconds = 1;
  2945.             TempCell.szCellDesc[0] = 0;
  2946.             TempCell.szCellPrefix[0] = 0;
  2947.             TempCell.szCellClickApp[0] = 0;
  2948.             TempCell.noCellOptions = DefaultNumberOptions;
  2949.           case D_Cell_Clone:
  2950.             TempCell.pszCellLog = NULL;
  2951.             TempCell.hCellHandle = NULLHANDLE;
  2952.             if ( EditCell( hwnd ) )
  2953.             {
  2954.               CellData *pNewCells = new CellData[iCellCount + 1];
  2955.               if ( pNewCells )
  2956.               {
  2957.                 TempCell.szCellData[0] = 0;
  2958.                 TempCell.iCellWidth = 0;
  2959.                 if ( pCells )
  2960.                 {
  2961.                   memcpy( pNewCells, pCells, iCellCount * sizeof( CellData ) );
  2962.                   delete pCells;
  2963.                 }
  2964.                 iCellCount++;
  2965.                 pCells = pNewCells;
  2966.                 pCells[iCellCount - 1] = TempCell;
  2967.                 InitCell( iCellCount - 1 );
  2968.                 WinSendDlgItemMsg( hwnd, D_Cell_List, LM_INSERTITEM, ( MPARAM )
  2969.                   LIT_END, MPFROMP( TempCell.szCellDesc ) );
  2970.                 WinSendDlgItemMsg( hwnd, D_Cell_List, LM_SELECTITEM,
  2971.                   ( MPARAM ) ( iCellCount - 1 ), ( MPARAM ) 1 );
  2972.               }
  2973.             }
  2974.             else if ( TempCell.pszCellLog ) delete TempCell.pszCellLog;
  2975.             break;
  2976.  
  2977.           case D_Cell_Remove:
  2978.             RemoveCell( i );
  2979.             WinSendDlgItemMsg( hwnd, D_Cell_List, LM_DELETEITEM,
  2980.               ( MPARAM ) i, ( MPARAM ) 0 );
  2981.             if ( iCellCount ) WinSendDlgItemMsg( hwnd, D_Cell_List,
  2982.               LM_SELECTITEM, ( MPARAM ) 0, ( MPARAM ) 1 );
  2983.             break;
  2984.  
  2985.           case D_Cell_Up:
  2986.           case D_Cell_Down:
  2987.             {
  2988.               int iOffset = SHORT1FROMMP( mp1 ) == D_Cell_Up ? -1 : 1;
  2989.               {
  2990.                 CellData tmp = pCells[i];
  2991.                 pCells[i] = pCells[i + iOffset];
  2992.                 pCells[i + iOffset] = tmp;
  2993.                 PaintCell( i, 1 );
  2994.                 PaintCell( i + iOffset, 1 );
  2995.               }
  2996.               WinSendDlgItemMsg( hwnd, D_Cell_List, LM_SETITEMTEXT,
  2997.                 ( MPARAM ) i, MPFROMP( pCells[i].szCellDesc ) );
  2998.               WinSendDlgItemMsg( hwnd, D_Cell_List, LM_SETITEMTEXT,
  2999.                 ( MPARAM ) ( i + iOffset ),
  3000.                 MPFROMP( pCells[i + iOffset].szCellDesc ) );
  3001.               WinSendDlgItemMsg( hwnd, D_Cell_List, LM_SELECTITEM,
  3002.                 ( MPARAM ) ( i + iOffset ), ( MPARAM ) 1 );
  3003.             }
  3004.             break;
  3005.  
  3006.         }
  3007.         EnableListButtons( hwnd );
  3008.       }
  3009.       break;
  3010.  
  3011.     case WM_CONTROL:
  3012.       switch ( SHORT1FROMMP( mp1 ) )
  3013.       {
  3014.         case D_Cell_List:
  3015.           if ( SHORT2FROMMP( mp1 ) == LN_SELECT )
  3016.           {
  3017.             int i = ( int ) WinSendDlgItemMsg( hwnd, D_Cell_List,
  3018.               LM_QUERYSELECTION, ( MPARAM ) LIT_CURSOR, ( MPARAM ) 0 );
  3019.             if ( i >= 0 && i < iCellCount ) TempCell = pCells[i];
  3020.             EnableMoveButtons( hwnd, i );
  3021.           }
  3022.           break;
  3023.       }
  3024.       break;
  3025.  
  3026.     default:
  3027.       return WinDefDlgProc( hwnd, msg, mp1, mp2 );
  3028.   }
  3029.   return ( MRESULT ) FALSE;
  3030. }
  3031.  
  3032.  
  3033.  
  3034.  
  3035. // Main properties dialog window procedure -----------------------------------
  3036. MRESULT EXPENTRY PropertiesDlgProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  3037. {
  3038.   static ULONG ulSettingsPage;
  3039.   static ULONG ulColorsPage;
  3040.   static ULONG ulNumberPage;
  3041.   static ULONG ulCellsPage;
  3042.   static ULONG ulAboutPage;
  3043.   static HWND hwSettingsDlg = NULL;
  3044.   static HWND hwColorsDlg = NULL;
  3045.   static HWND hwNumberDlg = NULL;
  3046.   static HWND hwCellsDlg = NULL;
  3047.   static HWND hwAboutDlg = NULL;
  3048.  
  3049.   switch ( msg )
  3050.   {
  3051.     case WM_INITDLG:
  3052.       if ( mp2 )
  3053.       {
  3054.         WinSetWindowText( hwnd, "SysBar/2 Pipe Monitor - Properties" );
  3055.         WinSendDlgItemMsg( hwnd, D_Prop_Notebook, BKM_SETNOTEBOOKCOLORS,
  3056.           MPFROMLONG( SYSCLR_DIALOGBACKGROUND ),
  3057.           MPFROMLONG( BKA_BACKGROUNDPAGECOLORINDEX ) );
  3058.         HWND hwNotebook = WinWindowFromID( hwnd, D_Prop_Notebook );
  3059.  
  3060.         ulSettingsPage = SB2_AddDlgPage( hwnd, D_Prop_Notebook, "Display",
  3061.           "Appearance settings (page 1 of 3)" );
  3062.         hwSettingsDlg = WinLoadDlg( hwNotebook, hwNotebook, SettingsDlgProc,
  3063.           ( HMODULE ) 0, DLG_SETTINGS, NULL );
  3064.         WinSendDlgItemMsg( hwnd, D_Prop_Notebook, BKM_SETPAGEWINDOWHWND,
  3065.           ( MPARAM ) ulSettingsPage, ( MPARAM ) hwSettingsDlg );
  3066.  
  3067.         ulColorsPage = ( ULONG ) WinSendDlgItemMsg( hwnd, D_Prop_Notebook,
  3068.           BKM_INSERTPAGE, ( MPARAM ) NULL, MPFROM2SHORT( ( BKA_MINOR |
  3069.           BKA_STATUSTEXTON | BKA_AUTOPAGESIZE ), BKA_LAST ) );
  3070.         WinSendMsg( hwNotebook, BKM_SETSTATUSLINETEXT, ( MPARAM ) ulColorsPage,
  3071.           MPFROMP ( "Cell colors (page 2 of 3)" ) );
  3072.         hwColorsDlg = WinLoadDlg( hwNotebook, hwNotebook, DefColourDlgProc,
  3073.           ( HMODULE ) 0, D_Cell_PageColors, NULL );
  3074.         WinSendMsg( hwNotebook, BKM_SETPAGEWINDOWHWND,
  3075.           ( MPARAM ) ulColorsPage, ( MPARAM ) hwColorsDlg );
  3076.  
  3077.         ulNumberPage = ( ULONG ) WinSendDlgItemMsg( hwnd, D_Prop_Notebook,
  3078.           BKM_INSERTPAGE, ( MPARAM ) NULL, MPFROM2SHORT( ( BKA_MINOR |
  3079.           BKA_STATUSTEXTON | BKA_AUTOPAGESIZE ), BKA_LAST ) );
  3080.         WinSendMsg( hwNotebook, BKM_SETSTATUSLINETEXT, ( MPARAM ) ulNumberPage,
  3081.           MPFROMP ( "Number display options (page 3 of 3)" ) );
  3082.         hwNumberDlg = WinLoadDlg( hwNotebook, hwNotebook, NumberDlgProc,
  3083.           ( HMODULE ) 0, D_Number_Dialog, NULL );
  3084.         WinSendMsg( hwNotebook, BKM_SETPAGEWINDOWHWND,
  3085.           ( MPARAM ) ulNumberPage, ( MPARAM ) hwNumberDlg );
  3086.  
  3087.         ulCellsPage = SB2_AddDlgPage( hwnd, D_Prop_Notebook, "Cells",
  3088.           "Information cells" );
  3089.         hwCellsDlg = WinLoadDlg( hwNotebook, hwNotebook, CellsDlgProc,
  3090.           ( HMODULE ) 0, D_Cell_Dialog, NULL );
  3091.         WinSendDlgItemMsg( hwnd, D_Prop_Notebook, BKM_SETPAGEWINDOWHWND,
  3092.           ( MPARAM ) ulCellsPage, ( MPARAM ) hwCellsDlg );
  3093.  
  3094.         ulAboutPage = SB2_AddDlgPage( hwnd, D_Prop_Notebook, "About",
  3095.           "About SysBar/2 Pipe Monitor" );
  3096.         hwAboutDlg = WinLoadDlg( hwNotebook, hwNotebook, AboutDlgProc,
  3097.           ( HMODULE ) 0, DLG_ABOUT, NULL );
  3098.         WinSendDlgItemMsg( hwnd, D_Prop_Notebook, BKM_SETPAGEWINDOWHWND,
  3099.           ( MPARAM ) ulAboutPage, ( MPARAM ) hwAboutDlg );
  3100.  
  3101.         WinSendDlgItemMsg( hwnd, D_Prop_Notebook, BKM_SETDIMENSIONS,
  3102.           MPFROM2SHORT ( 21, 21 ), MPFROMSHORT ( BKA_PAGEBUTTON ) );
  3103.         WinSendDlgItemMsg( hwnd, D_Prop_Notebook, BKM_SETDIMENSIONS,
  3104.           MPFROM2SHORT ( 80, 20 ), MPFROMSHORT ( BKA_MAJORTAB ) );
  3105.         WinSendDlgItemMsg( hwnd, D_Prop_Notebook, BKM_SETDIMENSIONS,
  3106.           MPFROM2SHORT ( 0, 0 ), MPFROMSHORT ( BKA_MINORTAB ) );
  3107.       }
  3108.       break;
  3109. /*
  3110.     case WM_COMMAND:
  3111.       switch ( SHORT1FROMMP( mp1 ) )
  3112.       {
  3113.         case DID_OK:
  3114.         case DID_CANCEL:
  3115.           WinDismissDlg( hwnd, SHORT1FROMMP( mp1 ) );
  3116.           break;
  3117.         default:
  3118.           return WinDefDlgProc( hwnd, msg, mp1, mp2 );
  3119.       }
  3120.       break;
  3121. */
  3122.     case WM_CLOSE:
  3123.       hwDlgToUpdate = NULL;
  3124.       WinDestroyWindow( hwSettingsDlg );
  3125.       WinDestroyWindow( hwNumberDlg );
  3126.       WinDestroyWindow( hwCellsDlg );
  3127.       WinDestroyWindow( hwAboutDlg );
  3128.       WinPostMsg( hwPipeClient, WM_COMMAND, ( MPARAM ) MNU_PIPE_SAVE, 0 );
  3129.     default:
  3130.       return WinDefDlgProc( hwnd, msg, mp1, mp2 );
  3131.   }
  3132.   return ( MRESULT ) FALSE;
  3133. }
  3134.  
  3135. HWND hwPrevWindow = HWND_DESKTOP;
  3136.  
  3137. void PopUpMainWindow( void )
  3138. {
  3139.   if ( iTopmost >= 2 ) hwPrevWindow = WinQueryWindow( hwPipeFrame, QW_PREV );
  3140.   WinSetWindowPos( hwPipeFrame, HWND_TOP, 0L, 0L, 0L, 0L,
  3141.     SWP_ZORDER | SWP_SHOW );
  3142.   bLastVisible = 1;
  3143. }
  3144.  
  3145.  
  3146.  
  3147.  
  3148.  
  3149. // Main window procedure -----------------------------------------------------
  3150. MRESULT EXPENTRY PipeWinProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  3151. {
  3152.   switch ( msg )
  3153.   {
  3154.     case WM_CREATE:
  3155.       {
  3156. //        HPS hps = WinGetPS( hwnd );
  3157. //        hbQ = GpiLoadBitmap( hps, NULLHANDLE, BMP_Q, 20, 20 );
  3158. //        WinReleasePS( hps );
  3159.         hmPopupMenu = WinLoadMenu( hwnd, NULLHANDLE, MNU_PIPE );
  3160.         MENUITEM mi;
  3161.         WinSendMsg( hmPopupMenu, MM_QUERYITEM,
  3162.           MPFROM2SHORT( MNU_PIPE_SUBMENU, TRUE ), MPFROMP( &mi ) );
  3163.         ULONG ulStyle = WinQueryWindowULong( mi.hwndSubMenu, QWL_STYLE );
  3164.         WinSetWindowULong( mi.hwndSubMenu, QWL_STYLE, ulStyle |
  3165.           MS_CONDITIONALCASCADE );
  3166.         WinStartTimer( hab, hwnd, TID_USERMAX + 9, 1000 );
  3167.       }
  3168.       break;
  3169.  
  3170.     case WM_COMMAND:
  3171.       {
  3172.         USHORT uCommand = SHORT1FROMMP( mp1 );
  3173.         HideDescWindow();
  3174.  
  3175.         switch ( uCommand )
  3176.         {
  3177.           case MNU_PIPE_SAVE:
  3178.             SaveOptions();
  3179.             break;
  3180.           case MNU_PIPE_PROPERTIES:
  3181.             WinDlgBox( HWND_DESKTOP, hwPipeFrame, PropertiesDlgProc,
  3182.               hmSysBar2Dll, DLG_PROPERTIES, ( PVOID ) &DummyInit );
  3183.             break;
  3184.           case MNU_PIPE_CLOSE:
  3185.             WinPostMsg( hwPipeFrame, WM_CLOSE, 0, 0 );
  3186.             break;
  3187.  
  3188.           case MNU_PIPE_LOCKPOSITION:
  3189.             bLockPosition ^= 1;
  3190.             break;
  3191.  
  3192.           case MNU_PIPE_NOTOP:
  3193.           case MNU_PIPE_TOPMOST:
  3194.           case MNU_PIPE_POPUP:
  3195.           case MNU_PIPE_POPUP2:
  3196.             iTopmost = uCommand - MNU_PIPE_NOTOP;
  3197.             break;
  3198.           case MNU_PIPE_SMALL:
  3199.           case MNU_PIPE_LARGE:
  3200.           case MNU_PIPE_AUTO:
  3201.           case MNU_PIPE_CUSTOM:
  3202.             iLarge = uCommand - int ( MNU_PIPE_SMALL );
  3203.             ResizeWindow();
  3204.             if ( iBindToCorner ) WinPostMsg( hwnd, WM_COMMAND,
  3205.               ( MPARAM ) ( MNU_PIPE_BIND_OFF + iBindToCorner ), 0 );
  3206.             break;
  3207.           case MNU_PIPE_BIND_OFF:
  3208.           case MNU_PIPE_BIND_NW:
  3209.           case MNU_PIPE_BIND_NE:
  3210.           case MNU_PIPE_BIND_SW:
  3211.           case MNU_PIPE_BIND_SE:
  3212.             if ( ( iBindToCorner = uCommand - MNU_PIPE_BIND_OFF ) > 0 )
  3213.             {
  3214.               int x = -1;
  3215.               int y = -1;
  3216.               if ( iBindToCorner == 1 || iBindToCorner == 2 )
  3217.                 y = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN ) -
  3218.                   iWindowHeight + 1;
  3219.               if ( iBindToCorner == 2 || iBindToCorner == 4 )
  3220.                 x = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN ) -
  3221.                   iWindowWidth + 1;
  3222.               WinSetWindowPos( hwPipeFrame, HWND_TOP, x, y, 0, 0, SWP_MOVE );
  3223.  
  3224.               int iNewOrientation = ( iBindToCorner & 1 ) ? 1 : 0;
  3225.               if ( iNewOrientation != iOrientation )
  3226.                 WinPostMsg( hwPipeClient, WM_COMMAND,
  3227.                   ( MPARAM ) ( MNU_PIPE_ORNT_LEFT + iNewOrientation ), 0 );
  3228.             }
  3229.             break;
  3230.           case MNU_PIPE_ORNT_LEFT:
  3231.           case MNU_PIPE_ORNT_RIGHT:
  3232.             iOrientation = int ( uCommand ) - MNU_PIPE_ORIENTATION - 1;
  3233.             ResizeWindow();
  3234.             UpdateSettingsDlg();
  3235.             if ( iBindToCorner ) WinPostMsg( hwnd, WM_COMMAND,
  3236.               ( MPARAM ) ( MNU_PIPE_BIND_OFF + iBindToCorner ), 0 );
  3237.             break;
  3238.  
  3239.           case MNU_PIPE_COPY:
  3240.             if ( iLastCell != -1 ) CopyCell( iLastCell );
  3241.             break;
  3242.  
  3243.           case MNU_PIPE_EMPTY:
  3244.             if ( iLastCell != -1 ) EmptyCell( iLastCell );
  3245.             break;
  3246.  
  3247.           case MNU_PIPE_REMOVE:
  3248.             if ( iLastCell != -1 )
  3249.             {
  3250.               RemoveCell( iLastCell );
  3251.               SaveOptions();
  3252.             }
  3253.             break;
  3254.  
  3255.           case MNU_PIPE_SETUP:
  3256.             if ( iLastCell != -1 )
  3257.             {
  3258.               EditCell( hwnd, iLastCell );
  3259.               SaveOptions();
  3260.             }
  3261.             break;
  3262.  
  3263.           case MNU_PIPE_EVENT:
  3264.             {
  3265.               NewCellData *p = ( NewCellData* ) mp2;
  3266.               if ( p )
  3267.               {
  3268.                 SetCellData( p->iIndex, p->szText );
  3269.                 delete p;
  3270.               }
  3271.             }
  3272.             break;
  3273.         }
  3274.       }
  3275.       break;
  3276.  
  3277.     case WM_BUTTON1DOWN:
  3278.       {
  3279.         bLastVisible = 0;
  3280.         iLastCell = iDescCell;
  3281.         HideDescWindow();
  3282.         if ( ! bLockPosition )
  3283.           WinPostMsg( hwPipeFrame, WM_TRACKFRAME, ( MPARAM ) TF_MOVE, 0L );
  3284.       }
  3285.       break;
  3286.  
  3287.     case WM_BUTTON1DBLCLK:
  3288.       bLastVisible = 0;
  3289.       if ( iLastCell >= 0 ) if ( pCells[iLastCell].szCellClickApp[0] &&
  3290.         ( pCells[iLastCell].iCellStatus & Cell_Click_App ) )
  3291.       {
  3292. /*
  3293.         CHAR LoadError[CCHMAXPATH] = { 0 };
  3294.         PSZ pszArgs = NULL;
  3295.         PSZ pszEnvs = NULL;
  3296.         RESULTCODES ChildRC = { 0 };
  3297.         DosExecPgm( LoadError, sizeof( LoadError ), EXEC_ASYNCRESULT, pszArgs,
  3298.           pszEnvs, &ChildRC, pPipes[iLastCell].szPipeExec );
  3299. */
  3300.         SpawnIt( pCells[iLastCell].szCellClickApp,
  3301.           pCells[iLastCell].szCellData );
  3302. //        spawnlp( P_NOWAIT, pCells[iLastCell].szCellClickApp,
  3303. //            pCells[iLastCell].szCellClickApp, NULL );
  3304.       }
  3305.       break;
  3306.  
  3307.     case WM_BUTTON2CLICK:
  3308.       {
  3309.         bLastVisible = 0;
  3310.         iLastCell = iDescCell;
  3311.         HideDescWindow();
  3312.         int x = SHORT1FROMMP( mp1 ),
  3313.           y = SHORT2FROMMP( mp1 );
  3314.         WinEnableMenuItem( hmPopupMenu, MNU_PIPE_SETUP, ( iLastCell > -1 ) );
  3315.         WinEnableMenuItem( hmPopupMenu, MNU_PIPE_SUBMENU, ( iLastCell > -1 ) );
  3316.         WinEnableMenuItem( hmPopupMenu, MNU_PIPE_COPY, ( iLastCell > -1 ) );
  3317.         bAlienMenu = 1;
  3318.         WinPopupMenu( hwnd, hwnd, hmPopupMenu, x, y, 0,
  3319.           PU_HCONSTRAIN | PU_VCONSTRAIN | PU_NONE |
  3320.           PU_KEYBOARD | PU_MOUSEBUTTON1 | PU_MOUSEBUTTON2 );
  3321.       }
  3322.       break;
  3323.  
  3324.     case WM_TIMER:
  3325.       switch ( ( USHORT ) ( mp1 ) )
  3326.       {
  3327.         case TID_USERMAX + 9:
  3328.           {
  3329.             DosPostEventSem( hevTimed );
  3330.             SWP swp;
  3331.             WinQueryWindowPos( hwPipeFrame, &swp );
  3332.             POINTL ptl = { 0, 0 };
  3333.             WinQueryPointerPos( HWND_DESKTOP, &ptl );
  3334.             ptl.x -= swp.x;
  3335.             ptl.y -= swp.y;
  3336.             AdjustDescPos( ptl.x, ptl.y );
  3337.  
  3338.             short int bOnTop = iTopmost;
  3339.  
  3340.             if ( iTopmost >= 2 )
  3341.             {
  3342.               SWP swp;
  3343.               WinQueryWindowPos( hwPipeFrame, &swp );
  3344.               POINTL ptl = { 0, 0 };
  3345.               WinQueryPointerPos( HWND_DESKTOP, &ptl );
  3346.               ptl.x -= swp.x;
  3347.               ptl.y -= swp.y;
  3348.               if ( ptl.x >= 0 && ptl.y >= 0 &&
  3349.                 ptl.x < iWindowWidth && ptl.y < iWindowHeight )
  3350.               {
  3351.                 if ( ! bLastVisible ) bLastVisible = bOnTop = 1;
  3352.               }
  3353.               else if ( bLastVisible )
  3354.               {
  3355.                 if ( iTopmost == 3 ) WinSetWindowPos( hwPipeFrame, hwPrevWindow,
  3356.                   0L, 0L, 0L, 0L, SWP_ZORDER );
  3357.                 bLastVisible = 0;
  3358.               }
  3359.             }
  3360.     
  3361.             if ( bOnTop == 1 ) PopUpMainWindow();
  3362.           }
  3363.           break;
  3364.       }
  3365.       break;
  3366.  
  3367.     case WM_ERASEBACKGROUND:
  3368.       bClearIt = 1;
  3369.       break;
  3370.  
  3371.     case WM_PAINT:
  3372.       {
  3373.         HPS hps;
  3374.         RECTL rc;
  3375.         hps = WinBeginPaint( hwnd, 0L, &rc );
  3376.  
  3377.         if ( bClearIt )
  3378.         {
  3379.           bClearIt = 0;
  3380.           SB2_Border( hps, 0, 0, iWindowWidth - 1, iWindowHeight - 1, 1,
  3381.             SB2c_Filler, 1 );
  3382.         }
  3383.         for ( int i = 0; i < iCellCount; i++ )
  3384.           if ( pCells[i].iCellWidth ) PaintCell( hps, i, 1 );
  3385.         WinEndPaint( hps );
  3386.       }
  3387.       break;
  3388.  
  3389.     case WM_CLOSE:
  3390.       HideDescWindow();
  3391.       SaveOptions();
  3392.       WinPostMsg( hwnd, WM_QUIT, 0, 0 );
  3393.       break;
  3394.  
  3395.     case WM_DESTROY:
  3396.       {
  3397.         for ( int i = 0; i < iCellCount; i++ )
  3398.         {
  3399.           ClosePipe( i );
  3400.           WriteCellLog( i, "*Closed*\n" );
  3401.         }
  3402.       }
  3403.       DosCloseEventSem( hevPipeGuard );
  3404.       DosCloseEventSem( hevTimed );
  3405.       DosCloseEventSem( hevHeavyTimed );
  3406.       WinStopTimer( hab, hwnd, TID_USERMAX + 9 );
  3407.       break;
  3408.  
  3409.     case WM_MENUEND:
  3410.       bAlienMenu = 0;
  3411.       break;
  3412.  
  3413.     case WM_MOUSEMOVE:
  3414.       if ( iTopmost >= 2 && ! bLastVisible ) PopUpMainWindow();
  3415.       AdjustDescPos( SHORT1FROMMP( mp1 ), SHORT2FROMMP( mp1 ), 0 );
  3416.     
  3417.     default:
  3418.       return WinDefWindowProc( hwnd, msg, mp1, mp2 );
  3419.   }
  3420.   return ( MRESULT ) FALSE;
  3421. }
  3422.  
  3423.  
  3424. char aStack[12288];
  3425.  
  3426. void FAR CheckStatus( void FAR *pParam )
  3427. {
  3428.   for ( int i = 0; i < iCellCount; i++ )
  3429.   {
  3430.     InitCell( i );
  3431.     WriteCellLog( i, "*Started*" );
  3432.   }
  3433.  
  3434.   ULONG uPosts;
  3435.   while ( 1 )
  3436.   {
  3437. /*
  3438.   if ( argc <= 1 ) return 1;
  3439.  
  3440.  
  3441.   iPipeCount = argc - 1;
  3442.   iPipeStatsCount = iPipeCount * 2;
  3443.   pPipeHandles = new HPIPE[iPipeCount];
  3444.   pPipeStates = new PIPESEMSTATE[iPipeStatsCount];
  3445.  
  3446.   for ( int i = 0; i < iPipeCount; i++ )
  3447.   {
  3448.     DosCreateNPipe( argv[i + 1], &pPipeHandles[i], NP_ACCESS_INBOUND,
  3449.       NP_NOWAIT | NP_TYPE_BYTE | NP_READMODE_BYTE | 1, iPipeBufSize,
  3450.       iPipeBufSize, 0L );
  3451.     DosSetNPipeSem( pPipeHandles[i], ( HSEM ) hevPipeGuard, i );
  3452.     DosConnectNPipe( pPipeHandles[i] );
  3453.   }
  3454.  
  3455.   while ( 1 )
  3456.   {
  3457.     ULONG uPosts;
  3458. */
  3459.       DosResetEventSem( hevPipeGuard, &uPosts );
  3460.       if ( DosWaitEventSem( hevPipeGuard, SEM_INDEFINITE_WAIT ) ) break;
  3461.       int iPipeStatsCount = ( iPipeCount << 1 );
  3462.       PPIPESEMSTATE pPipeStates = new PIPESEMSTATE[iPipeStatsCount];
  3463.       if ( pPipeStates )
  3464.       {
  3465.         DosQueryNPipeSemState( ( HSEM ) hevPipeGuard, pPipeStates,
  3466.           sizeof ( PIPESEMSTATE ) * iPipeStatsCount );
  3467.         for ( int i = iPipeStatsCount - 1; i >= 0; i-- )
  3468.         {
  3469.           if ( pPipeStates[i].fStatus )
  3470.           {
  3471.             int iIndex;
  3472.             for ( iIndex = 0; iIndex < iCellCount; iIndex++ )
  3473.               if ( pPipeStates[i].usKey == pCells[iIndex].iCellIndex ) break;
  3474.             if ( iIndex < iCellCount ) switch ( pPipeStates[i].fStatus )
  3475.             {
  3476.               case NPSS_RDATA:
  3477.                 {
  3478.                   ULONG iCount = 0;
  3479.                   while ( DosRead( pCells[iIndex].hCellHandle, PipeBuffer,
  3480.                     iPipeBufSize - 1, &iCount ) == 0 )
  3481.                   {
  3482.                     if ( iCount )
  3483.                     {
  3484.                       PipeBuffer[iCount] = 0;
  3485.                       NewCellData *p = new NewCellData;
  3486.                       if ( p )
  3487.                       {
  3488.                         p->iIndex = iIndex;
  3489.                         memset( p->szText, 0, iPipeBufSize );
  3490.                         strncpy( p->szText, ( char* ) PipeBuffer,
  3491.                           iPipeBufSize - 1 );
  3492.                         WinPostMsg( hwPipeClient, WM_COMMAND,
  3493.                           ( MPARAM ) MNU_PIPE_EVENT, ( MPARAM ) p );
  3494.                       }
  3495.                     }
  3496.                     else
  3497.                     {
  3498.                       ResetPipe( iIndex );
  3499.                       break;
  3500.                     }
  3501.                   }
  3502.                 }
  3503.                 break;
  3504.  
  3505.               case NPSS_CLOSE:
  3506.                 ResetPipe( iIndex );
  3507.                 break;
  3508.             }
  3509.           }
  3510.         }
  3511.         delete pPipeStates;
  3512.       }
  3513. /*
  3514.     for ( int i = iPipeStatsCount - 1; i >= 0; i-- )
  3515.     {
  3516.       switch ( pPipeStates[i].fStatus )
  3517.       {
  3518.         case NPSS_RDATA:
  3519.           {
  3520.             ULONG iCount = 0;
  3521.             while ( DosRead( pPipeHandles[pPipeStates[i].usKey], PipeBuffer,
  3522.               iPipeBufSize, &iCount ) == 0 )
  3523.             {
  3524.               if ( iCount )
  3525.               {
  3526.                 PipeBuffer[iCount] = 0;
  3527.                 printf( "[#i]  read %i bytes: <%s>\n",
  3528.                   pPipeStates[i].usKey, iCount, PipeBuffer );
  3529.               }
  3530.               else break;
  3531.             }
  3532.           }
  3533.           break;
  3534.  
  3535.         case NPSS_CLOSE:
  3536.           DosDisConnectNPipe( pPipeHandles[pPipeStates[i].usKey] );
  3537.           DosConnectNPipe( pPipeHandles[pPipeStates[i].usKey] );
  3538.           break;
  3539.       }
  3540.     }
  3541.   }
  3542.  
  3543.   for ( i = 0; i < iPipeCount; i++ )
  3544.   {
  3545.     DosDisConnectNPipe( pPipeHandles[i] );
  3546.     DosClose( pPipeHandles[i] );
  3547.   }
  3548.  
  3549.   delete pPipeHandles;
  3550.   delete pPipeStates;
  3551. */
  3552.   }
  3553.   _endthread();
  3554. }
  3555.  
  3556.  
  3557. typedef struct
  3558. {
  3559.   USHORT usParmLength;
  3560.   USHORT usPowerFlags;
  3561.   UCHAR ucACStatus;
  3562.   UCHAR ucBatteryStatus;
  3563.   UCHAR ucBatteryLife;
  3564. } IOCTLPowerStatus;
  3565. #define IOCTL_POWER 0x000C
  3566. #define POWER_GETPOWERSTATUS 0x0060
  3567.  
  3568. #define PQ_BUFSIZE  0x10000
  3569.  
  3570. char aStack2[12288];
  3571.  
  3572. struct ifmib Ifmib;
  3573. short int bIfmibUpdated;
  3574. time_t tIfmibTime = 0;
  3575. int iIfmibSocket = -1;
  3576.  
  3577. void FAR TimedProcedure( void FAR *pParam )
  3578. {
  3579.   ULONG uPosts;
  3580.   ProcessCollection pcList;
  3581.   static FSALLOCATE fsa;
  3582.  
  3583.   while ( 1 )
  3584.   {
  3585.     DosResetEventSem( hevTimed, &uPosts );
  3586.     if ( DosWaitEventSem( hevTimed, SEM_INDEFINITE_WAIT ) ) break;
  3587.     int iHeavyCells = 0;
  3588.     bIfmibUpdated = 0;
  3589.     for ( int i = 0; i < iCellCount; i++ )
  3590.       if ( pCells[i].iCellStatus & Cell_Enabled )
  3591.     {
  3592.       if ( pCells[i].iCellLazyCounter ) pCells[i].iCellLazyCounter--;
  3593.       if ( --( pCells[i].iCellCounter ) > 0 ) continue;
  3594.  
  3595.       NewCellData *p = NULL;
  3596.       switch ( pCells[i].iCellType )
  3597.       {
  3598.         case MCT_Pipe:
  3599.           if ( ( pCells[i].iCellStatus & Cell_Expire ) && pCells[i].iCellWidth )
  3600.             EmptyCell( i );
  3601.           break;
  3602.         case MCT_CPULoad:
  3603.           {
  3604.             if ( p = new NewCellData )
  3605.             {
  3606.               int iLoad = 1;
  3607.               if ( ( dpsc ) && ( pCells[i].iCellStatus & Cell_Check1 ) )
  3608.               {
  3609.                 CPUUTIL cpuu[CPUS];
  3610.                 ULLONG* pdTimePrev = ( (ULLONG*) pCells[i].szCellData0 );
  3611.                 ULLONG* pdBusyPrev = ( (ULLONG*) pCells[i].szCellData0 ) + CPUS;
  3612.                 if ( ! dpsc( CMD_KI_RDCNT, ( ULONG ) &cpuu[0], 0, 0 ) )
  3613.                 {
  3614.                   int cpun = 0;
  3615.                   if(pCells[i].iCellStatus & Cell_Check2) cpun = 1;
  3616.                   ULLONG dTime = LL2F( cpuu[cpun].ulTimeHigh, cpuu[cpun].ulTimeLow );
  3617.                   ULLONG dBusy = LL2F( cpuu[cpun].ulBusyHigh, cpuu[cpun].ulBusyLow );
  3618.                   if( dTime == pdTimePrev[cpun] ) iLoad = 0;
  3619.                   else iLoad = (dBusy - pdBusyPrev[cpun])*100 / (dTime - pdTimePrev[cpun]);
  3620.                   pdTimePrev[cpun] = dTime;
  3621.                   pdBusyPrev[cpun] = dBusy;
  3622.                 }
  3623.               }
  3624.               else
  3625.               {
  3626.                 pcList.CollectData();
  3627.                 iLoad = pcList.GetCPULoad();
  3628.                 if ( iLoad < 0 ) iLoad = 0;
  3629.               }
  3630.               int iMaxLoad = ( pCells[i].iCellStatus & Cell_Check0 ) ? 99 : 100;
  3631.               if ( iLoad > iMaxLoad ) iLoad = iMaxLoad;
  3632.               if ( iLoad >= 0 ) sprintf( p->szText , "%02d%%", iLoad );
  3633.             }
  3634.           }
  3635.           break;
  3636.         case MCT_PhysMem:
  3637.           {
  3638.             if ( p = new NewCellData )
  3639.             {
  3640.               ULONG ulPhysMemFree;
  3641.               APIRET16 rc = Dos16MemAvail( &ulPhysMemFree );
  3642.               p->szText[0] = 0;
  3643.               FormatNumber( p->szText, &( pCells[i].noCellOptions ),
  3644.                 ULLONG(ulPhysMemFree) );
  3645.             }
  3646.           }
  3647.           break;
  3648.         case MCT_Power:
  3649.           {
  3650.             HFILE hAPM;
  3651.             ULONG ulAction;
  3652.             DosOpen( "APM$", &hAPM, &ulAction, 0, 0,
  3653.               OPEN_ACTION_OPEN_IF_EXISTS,
  3654.               OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE, NULL );
  3655.             if ( p = new NewCellData )
  3656.             {
  3657.               strcpy( p->szText, pszErrors[APM_CantInit] );
  3658.               IOCTLPowerStatus BatStatus;
  3659.               BatStatus.usParmLength = 7;
  3660.               ULONG ulSize = sizeof( BatStatus );
  3661.               USHORT usRet;
  3662.               ULONG usRetSize = sizeof( usRet );
  3663.               if ( hAPM )
  3664.               {
  3665.                 APIRET rc = DosDevIOCtl( ( HFILE ) hAPM, IOCTL_POWER,
  3666.                   POWER_GETPOWERSTATUS, ( PVOID ) &BatStatus,
  3667.                   sizeof( BatStatus ), &ulSize, ( PVOID ) &usRet,
  3668.                   sizeof( usRet ), &usRetSize );
  3669.                 if ( BatStatus.ucACStatus == 1 || BatStatus.ucACStatus == 0 )
  3670.                 {
  3671.                   strcpy( p->szText, BatStatus.ucACStatus == 1 ? "AC" : "DC" );
  3672.                   if ( BatStatus.ucBatteryLife <= 100 ) sprintf( p->szText + 2,
  3673.                     ": %i%%", ( int ) BatStatus.ucBatteryLife );
  3674.                 }
  3675.                 DosClose( hAPM );
  3676.               }
  3677.             }
  3678.           }
  3679.           break;
  3680.         case MCT_FreeSpace:
  3681.           {
  3682.             memset( &fsa, 0, sizeof( FSALLOCATE ) );
  3683.             if ( p = new NewCellData )
  3684.             {
  3685.               DosQueryFSInfo( pCells[i].szCellData1[0] - '0' + 1, FSIL_ALLOC,
  3686.                 ( void * ) &fsa, sizeof( FSALLOCATE ) );
  3687.               ULLONG dSize = ULLONG( fsa.cUnitAvail ) *
  3688.                 ULLONG( fsa.cSectorUnit ) * ULLONG( fsa.cbSector );
  3689.               p->szText[0] = 0;
  3690.               if ( dSize > 0 )
  3691.                 FormatNumber( p->szText, &( pCells[i].noCellOptions ), dSize );
  3692.             }
  3693.           }
  3694.           break;
  3695.         case MCT_Clock:
  3696.           {
  3697.             if ( p = new NewCellData )
  3698.               FormatDateTime( p->szText, pCells[i].iCellStatus );
  3699.           }
  3700.           break;
  3701.         case MCT_Uptime:
  3702.           {
  3703.             if ( p = new NewCellData )
  3704.               FormatDateTime( p->szText, pCells[i].iCellStatus, 0, FDT_Uptime );
  3705.           }
  3706.           break;
  3707.         case MCT_Calendar:
  3708.           {
  3709.             if ( p = new NewCellData )
  3710.               FormatDateTime( p->szText, 0, pCells[i].iCellStatus, FDT_Date );
  3711.           }
  3712.           break;
  3713.         case MCT_Processes:
  3714.           {
  3715.             if ( p = new NewCellData )
  3716.             {
  3717.               p->szText[0] = 0;
  3718.               int iDisplayed = 0;
  3719.               if ( pCells[i].iCellStatus & Cell_Check0 )
  3720.               {
  3721.                 sprintf( p->szText, "%lu", WinQuerySwitchList( hab, NULL, 0 ) );
  3722.                 iDisplayed++;
  3723.               }
  3724.               if ( pCells[i].iCellStatus &
  3725.                 ( Cell_Check1 | Cell_Check2 | Cell_Check3 ) )
  3726.               {
  3727.                 PQTOPLEVEL pqData = ( PQTOPLEVEL ) new char[PQ_BUFSIZE];
  3728.                 if ( pqData )
  3729.                 {
  3730.                   memset( pqData, 0, PQ_BUFSIZE );
  3731.                   if ( ! DosQuerySysState( 1, 0, 0, 0, pqData, PQ_BUFSIZE ) )
  3732.                   {
  3733.                     PQGLOBAL pqGlobal = pqData->gbldata;
  3734.                     if ( pCells[i].iCellStatus & Cell_Check1 )
  3735.                       sprintf( p->szText + strlen( p->szText ), "%s%lu",
  3736.                         iDisplayed++ ? "/" : "", pqGlobal->threadcnt );
  3737.                     if ( pCells[i].iCellStatus & Cell_Check2 )
  3738.                       sprintf( p->szText + strlen( p->szText ), "%s%lu",
  3739.                         iDisplayed++ ? "/" : "", pqGlobal->modulecnt );
  3740. //                    if ( pCells[i].iCellStatus & Cell_Check3 )
  3741. //                      sprintf( p->szText + strlen( p->szText ), "%s%lu",
  3742. //                        iDisplayed++ ? "/" : "", pqGlobal->proccnt );
  3743.                   }
  3744.                   delete pqData;
  3745.                 }
  3746.               }
  3747.             }
  3748.           }
  3749.           break;
  3750.         case MCT_FileSize:
  3751.           {
  3752.             if ( p = new NewCellData )
  3753.             {
  3754.               HDIR hFindHandle = HDIR_SYSTEM;
  3755.               FILEFINDBUF3 FindBuffer = { 0 };
  3756.               ULONG ulResultBufLen = sizeof( FILEFINDBUF3 );
  3757.               ULONG ulFindCount = 1;
  3758.               ULLONG dSize = 0;
  3759.               int iCount = 0;
  3760.  
  3761.               if ( DosFindFirst( pCells[i].szCellData1, &hFindHandle,
  3762.                 FILE_NORMAL/* | FILE_READONLY | FILE_SYSTEM | FILE_HIDDEN |
  3763.                 FILE_ARCHIVED*/, &FindBuffer, ulResultBufLen, &ulFindCount,
  3764.                 FIL_STANDARD ) == NO_ERROR )
  3765.               {
  3766.                 do
  3767.                 {
  3768.                   dSize += FindBuffer.cbFile;
  3769.                   iCount++;
  3770.                 }
  3771.                 while ( DosFindNext( hFindHandle, &FindBuffer, ulResultBufLen,
  3772.                   &ulFindCount ) == NO_ERROR );
  3773.               }
  3774.               DosFindClose( hFindHandle );
  3775.  
  3776.               p->szText[0] = 0;
  3777.               FormatCount( p->szText, iCount, dSize, &pCells[i] );
  3778.             }
  3779.           }
  3780.           break;
  3781.  
  3782.         case MCT_TrafIn:
  3783.         case MCT_TrafOut:
  3784.           {
  3785.             if ( p = new NewCellData )
  3786.             {
  3787.               p->szText[0] = 0;
  3788.               if ( iIfmibSocket == -1 )
  3789.                 iIfmibSocket = Socket( PF_INET, SOCK_STREAM, 0 );
  3790.               if ( iIfmibSocket != -1 )
  3791.               {
  3792.                 if ( ! bIfmibUpdated )
  3793.                 {
  3794.                   memset( &Ifmib, 0, sizeof ( struct ifmib ) );
  3795.                   SoIOCtl( iIfmibSocket, SIOSTATIF,
  3796.                     ( caddr_t ) &Ifmib, sizeof ( struct ifmib ) );
  3797.                   tIfmibTime = time( NULL );
  3798.                   bIfmibUpdated = 1;
  3799.                 }
  3800.                 for ( int j = 0; j < IFMIB_ENTRIES; j++ )
  3801.                 {
  3802.                   if ( Ifmib.iftable[j].iftIndex == *(int*)pCells[i].szCellData1 )
  3803.                   {
  3804.                     TrafData* pTrafData = ( TrafData* ) pCells[i].szCellData0;
  3805.                     int iOctets = ( pCells[i].iCellType == MCT_TrafIn ?
  3806.                       Ifmib.iftable[j].iftInOctets :
  3807.                       Ifmib.iftable[j].iftOutOctets );
  3808.                     if ( pTrafData->uInitialized != TRAF_INIT )
  3809.                     {
  3810.                       pTrafData->uInitialized = TRAF_INIT;
  3811.                       pTrafData->tInitialTime = pTrafData->tLastTime = tIfmibTime;
  3812.                       pTrafData->lMaxCPS = 0;
  3813.                       pTrafData->lBytes = 0;
  3814.                       pTrafData->uInitialOctets = pTrafData->iLastOctets = iOctets;
  3815.                     }
  3816.                     else
  3817.                     {
  3818.                       ULLONG dCPS = (ULONG)(iOctets - pTrafData->iLastOctets);
  3819.                       pTrafData->lBytes += dCPS;
  3820.  
  3821.                       if( tIfmibTime != pTrafData->tLastTime ) {
  3822.                         dCPS /= (tIfmibTime - pTrafData->tLastTime);
  3823.                         if ( pTrafData->lMaxCPS < dCPS ) pTrafData->lMaxCPS = dCPS;
  3824.                       }
  3825.  
  3826.                       int iDisplayed = 0;
  3827.                       if ( pCells[i].iCellStatus & Cell_Check0 )
  3828.                         FormatNumber( p->szText, &( pCells[i].noCellOptions ),
  3829.                           dCPS, iDisplayed++ );
  3830.                       if ( pCells[i].iCellStatus & Cell_Check1 )
  3831.                         FormatNumber( p->szText, &( pCells[i].noCellOptions ),
  3832.                           pTrafData->lBytes / (tIfmibTime - pTrafData->tInitialTime),
  3833.                           iDisplayed++ );
  3834.                       if ( pCells[i].iCellStatus & Cell_Check2 )
  3835.                         FormatNumber( p->szText, &( pCells[i].noCellOptions ),
  3836.                           pTrafData->lMaxCPS, iDisplayed++ );
  3837.                       if ( pCells[i].iCellStatus & Cell_Check3 )
  3838.                         FormatNumber( p->szText, &( pCells[i].noCellOptions ),
  3839.                           pTrafData->uInitialOctets + pTrafData->lBytes, iDisplayed );
  3840.  
  3841.                       pTrafData->tLastTime = tIfmibTime;
  3842.                       pTrafData->iLastOctets = iOctets;
  3843.                     }
  3844.                     break;
  3845.                   }
  3846.                 }
  3847.               }
  3848.             }
  3849.           }
  3850.           break;
  3851.  
  3852.  
  3853.         default:
  3854.           iHeavyCells++;
  3855.           pCells[i].hCellHandle = 1;
  3856.           break;
  3857.       }
  3858.  
  3859.       if ( p )
  3860.       {
  3861.         p->iIndex = i;
  3862.         WinPostMsg( hwPipeClient, WM_COMMAND, ( MPARAM ) MNU_PIPE_EVENT,
  3863.           ( MPARAM ) p );
  3864.       }
  3865.  
  3866.       pCells[i].iCellCounter = pCells[i].iCellSeconds;
  3867.     }
  3868.     if ( iHeavyCells ) DosPostEventSem( hevHeavyTimed );
  3869.   }
  3870.   _endthread();
  3871. }
  3872.  
  3873. char aStack3[12288];
  3874.  
  3875. int RecvData( int iSocket, char* pszBuf, int iBufSize )
  3876. {
  3877.   int iBytes = 0, l = 0;
  3878.   for ( ; iBufSize > 0; pszBuf += l, iBufSize -= l )
  3879.   {
  3880.     if ( ( l = Recv( iSocket, pszBuf, iBufSize, 0 ) ) > 0 )
  3881.     {
  3882.       pszBuf[l] = 0;
  3883.       iBytes += l;
  3884.       if ( pszBuf[l - 1] == '\n' || pszBuf[l - 1] == '\r' ) break;
  3885.     }
  3886.     else break;
  3887.   }
  3888.   return iBytes;
  3889. }
  3890.  
  3891. void FAR HeavyTimedProcedure( void FAR *pParam )
  3892. {
  3893.   ULONG uPosts;
  3894.   char szBuf[128];
  3895.   long l;
  3896.  
  3897.   while ( 1 )
  3898.   {
  3899.     DosResetEventSem( hevHeavyTimed, &uPosts );
  3900.     if ( DosWaitEventSem( hevHeavyTimed, SEM_INDEFINITE_WAIT ) ) break;
  3901.     for ( int i = 0; i < iCellCount; i++ )
  3902.       if ( pCells[i].iCellStatus & Cell_Enabled && pCells[i].hCellHandle )
  3903.     {
  3904.       NewCellData *p = NULL;
  3905.       switch ( pCells[i].iCellType )
  3906.       {
  3907.         case MCT_POP3:
  3908.           {
  3909.             pCells[i].hCellHandle = 0;
  3910.             if ( p = new NewCellData )
  3911.             {
  3912.               p->szText[0] = 0;
  3913.               short int bShowErrors = pCells[i].iCellStatus & Cell_Check2;
  3914.               short int bWriteLog = ( ( pCells[i].iCellStatus & ( Cell_Log_On |
  3915.                 Cell_Check3 ) ) == ( Cell_Log_On | Cell_Check3 ) );
  3916.  
  3917.               Pop3URL* pUrl = ( Pop3URL* ) pCells[i].szCellData0;
  3918.               unsigned long ulAddress = InetAddr( pUrl->pszHost );
  3919.               if ( ulAddress == -1L )
  3920.               {
  3921.                 struct hostent *hp = GetHostByName( pUrl->pszHost );
  3922.                 if ( hp ) ulAddress = *( unsigned long* ) hp->h_addr;
  3923.               }
  3924.               if ( ulAddress == -1L )
  3925.               {
  3926.                 if ( bShowErrors ) sprintf( p->szText,
  3927.                   pszErrors[P3E_UnknownHost], pUrl->pszHost );
  3928.                 break;
  3929.               }
  3930.  
  3931.               int iSocket = Socket( AF_INET, SOCK_STREAM, 0 );
  3932.               if ( iSocket == -1 )
  3933.               {
  3934.                 if ( bShowErrors )
  3935.                   sprintf( p->szText, pszErrors[P3E_Socket] );
  3936.                 break;
  3937.               }
  3938.               sockaddr_in sa;
  3939.               memset( &sa, 0, sizeof ( sa ) );
  3940.               sa.sin_family = AF_INET;
  3941.               sa.sin_addr.s_addr = ulAddress;
  3942.               sa.sin_port = BSwap( pUrl->iPort );
  3943.               Connect( iSocket, ( struct sockaddr* ) &sa, sizeof ( sa ) );
  3944.  
  3945.               do
  3946.               {
  3947.                 l = RecvData( iSocket, szBuf, sizeof ( szBuf ) );
  3948.                 if ( l <= 0 )
  3949.                 {
  3950.                   if ( bShowErrors ) sprintf( p->szText,
  3951.                     pszErrors[P3E_CantReach], pUrl->pszHost );
  3952.                   break;
  3953.                 }
  3954.                 else
  3955.                 {
  3956.                   szBuf[l] = 0;
  3957.                   if ( bWriteLog ) WriteCellLog( i, szBuf, 1 );
  3958.                 }
  3959.  
  3960.                 sprintf( szBuf, "USER %s\r\n", pUrl->pszUsername );
  3961.                 if ( Send( iSocket, szBuf, strlen( szBuf ), 0 ) <= 0 )
  3962.                 {
  3963.                   if ( bShowErrors ) sprintf( p->szText,
  3964.                     pszErrors[P3E_UserSnd], pUrl->pszUsername );
  3965.                   break;
  3966.                 }
  3967.                 else if ( bWriteLog ) WriteCellLog( i, szBuf, 1 );
  3968.                 if ( ( l = RecvData( iSocket, szBuf, sizeof ( szBuf ) ) ) <= 0 )
  3969.                 {
  3970.                   if ( bShowErrors ) sprintf( p->szText,
  3971.                     pszErrors[P3E_UserRcv], pUrl->pszUsername );
  3972.                   break;
  3973.                 }
  3974.                 else
  3975.                 {
  3976.                   szBuf[l] = 0;
  3977.                   if ( bWriteLog ) WriteCellLog( i, szBuf, 1 );
  3978.                 }
  3979.                 if ( szBuf[0] == '-' )
  3980.                 {
  3981.                   if ( bShowErrors ) sprintf( p->szText,
  3982.                     pszErrors[P3E_User], pUrl->pszUsername );
  3983.                   break;
  3984.                 }
  3985.  
  3986.                 sprintf( szBuf, "PASS %s\r\n", pUrl->pszPassword );
  3987.                 if ( Send( iSocket, szBuf, strlen( szBuf ), 0 ) <=0 )
  3988.                 {
  3989.                   if ( bShowErrors ) sprintf( p->szText,
  3990.                     pszErrors[P3E_PasswordSnd], pUrl->pszUsername );
  3991.                   break;
  3992.                 }
  3993.                 else if ( bWriteLog ) WriteCellLog( i, szBuf, 1 );
  3994.                 if ( ( l = RecvData( iSocket, szBuf, sizeof ( szBuf ) ) ) <= 0 )
  3995.                 {
  3996.                   if ( bShowErrors ) sprintf( p->szText,
  3997.                     pszErrors[P3E_PasswordRcv], pUrl->pszUsername );
  3998.                   break;
  3999.                 }
  4000.                 else
  4001.                 {
  4002.                   szBuf[l] = 0;
  4003.                   if ( bWriteLog ) WriteCellLog( i, szBuf, 1 );
  4004.                 }
  4005.                 if ( szBuf[0] == '-' )
  4006.                 {
  4007.                   if ( bShowErrors ) sprintf( p->szText,
  4008.                     pszErrors[P3E_Password], pUrl->pszUsername );
  4009.                   break;
  4010.                 }
  4011.  
  4012.                 sprintf( szBuf, "STAT\r\n" );
  4013.                 if ( Send( iSocket, szBuf, strlen( szBuf ), 0 ) <=0 )
  4014.                 {
  4015.                   if ( bShowErrors ) sprintf( p->szText,
  4016.                     pszErrors[P3E_StatSnd], pUrl->pszUsername );
  4017.                   break;
  4018.                 }
  4019.                 else if ( bWriteLog ) WriteCellLog( i, szBuf, 1 );
  4020.                 if ( ( l = RecvData( iSocket, szBuf, sizeof ( szBuf ) ) ) <= 0 )
  4021.                 {
  4022.                   if ( bShowErrors ) sprintf( p->szText,
  4023.                     pszErrors[P3E_StatRcv], pUrl->pszUsername );
  4024.                   break;
  4025.                 }
  4026.                 else
  4027.                 {
  4028.                   szBuf[l] = 0;
  4029.                   if ( bWriteLog ) WriteCellLog( i, szBuf, 1 );
  4030.                 }
  4031.                 if ( szBuf[0] == '-' )
  4032.                 {
  4033.                   if ( bShowErrors ) sprintf( p->szText,
  4034.                     pszErrors[P3E_Stat], pUrl->pszUsername );
  4035.                   break;
  4036.                 }
  4037.                 else
  4038.                 {
  4039.                   if ( pCells[i].iCellStatus & Cell_Check3 )
  4040.                     strcpy( p->szText, szBuf );
  4041.                   else
  4042.                   {
  4043.                     ULLONG iCount = 0, iSize = 0;
  4044.                     sscanf( szBuf, "+OK %I64u %I64u", &iCount, &iSize );
  4045.                     if ( iCount > 0 ) FormatCount( p->szText, iCount,
  4046.                       iSize, &pCells[i] );
  4047.                   }
  4048.                 }
  4049.               }
  4050.               while ( 0 );
  4051.               sprintf( szBuf, "QUIT\r\n" );
  4052.               Send( iSocket, szBuf, strlen( szBuf ), 0 );
  4053.               if ( bWriteLog ) WriteCellLog( i, szBuf, 1 );
  4054.               SoClose( iSocket );
  4055.  
  4056.             }
  4057.           }
  4058.           break;
  4059.       }
  4060.  
  4061.       if ( p )
  4062.       {
  4063.         p->iIndex = i;
  4064.         WinPostMsg( hwPipeClient, WM_COMMAND, ( MPARAM ) MNU_PIPE_EVENT,
  4065.           ( MPARAM ) p );
  4066.       }
  4067.     }
  4068.   }
  4069.   _endthread();
  4070. }
  4071.  
  4072.  
  4073. ULONG APIENTRY BugHandler( PEXCEPTIONREPORTRECORD p1,
  4074.   PEXCEPTIONREGISTRATIONRECORD p2, PCONTEXTRECORD p3, PVOID pv)
  4075. {
  4076.   if ( p1->ExceptionNum == XCPT_ACCESS_VIOLATION &&
  4077.     p1->ExceptionInfo[1] == 0xFFFFFFFF && p1->ExceptionInfo[0] == 0 )
  4078.     return XCPT_CONTINUE_EXECUTION;
  4079.   else return XCPT_CONTINUE_SEARCH;
  4080. }
  4081.  
  4082.  
  4083. // Main procedure ------------------------------------------------------------
  4084. int main( int argc, char *argv[] )
  4085. {
  4086.   HMQ hmq;
  4087.   QMSG qmsg;
  4088.   char szClassName[] = "SysBar2PipeClass";
  4089.   char szDescClassName[] = "SysBar2PipeDescClass";
  4090.  
  4091.   memset( &fd, 0, sizeof ( FONTDLG ) );
  4092.   fd.cbSize = sizeof ( FONTDLG );
  4093.   fd.pszFamilyname = szFamilyname;
  4094.   fd.usFamilyBufLen = sizeof ( szFamilyname );
  4095.   fd.fl = FNTS_BITMAPONLY | FNTS_CENTER | FNTS_INITFROMFATTRS;
  4096.  
  4097.   if ( ( hab = WinInitialize( 0 ) ) == 0L ) AbortStartup();
  4098.   if ( ( hmq = WinCreateMsgQueue( hab, 0 ) ) == 0L ) AbortStartup();
  4099.  
  4100.   {
  4101.     EXCEPTIONREGISTRATIONRECORD RegRec = { 0 };
  4102.     RegRec.ExceptionHandler = ( ERR ) BugHandler;
  4103.     if ( DosSetExceptionHandler( &RegRec ) != NO_ERROR ) AbortStartup();
  4104.   }
  4105.  
  4106.   hmSysBar2Dll = SB2_Init();
  4107.   iDefaultBackColor = SB2_ColorCount() - 1;
  4108.  
  4109.   if ( ! DosLoadModule( NULL, 0, "DOSCALL1.DLL", &hmDosCall1 ) )
  4110.     DosQueryProcAddr( hmDosCall1, 976, "DosPerfSysCall", ( PFN* ) &dpsc );
  4111.   if ( dpsc ) dpsc(CMD_KI_ENABLE, 0, 0, 0);
  4112.   else pszCellCheckNames[MCT_CPULoad][1] = NULL;
  4113.  
  4114.   int n = 0;
  4115.   if ( ! DosLoadModule( NULL, 0, "SO32DLL.DLL", &hmSo32DLL ) &&
  4116.     ! DosLoadModule( NULL, 0, "TCP32DLL.DLL", &hmTCP32DLL ) )
  4117.   {
  4118.     for ( int i = 0; i < iSocketCallCount; i++ ) if ( ! DosQueryProcAddr(
  4119.       i < iTCPCallCount ? hmTCP32DLL : hmSo32DLL, 0, pszSocketCalls[i],
  4120.       pSocketFns[i] ) ) n++;
  4121.   }
  4122.   if ( n < iSocketCallCount )
  4123.   {
  4124.     if ( hmSo32DLL ) DosFreeModule( hmSo32DLL );
  4125.     if ( hmTCP32DLL ) DosFreeModule( hmTCP32DLL );
  4126.     hmSo32DLL = NULLHANDLE;
  4127.     hmTCP32DLL = NULLHANDLE;
  4128.   }
  4129.  
  4130.   if ( ! WinRegisterClass( hab, ( PSZ ) szClassName, 
  4131.     ( PFNWP ) PipeWinProc, 0L, 0 ) ) AbortStartup();
  4132.   if ( ! WinRegisterClass( hab, ( PSZ ) szDescClassName,
  4133.     ( PFNWP ) SwDescWinProc, CS_SIZEREDRAW, 0 ) ) AbortStartup();
  4134.  
  4135.   {
  4136.     TIB *tib;
  4137.     PIB *pib;
  4138.     DosGetInfoBlocks( &tib, &pib );
  4139.     char szSemName[48];
  4140.  
  4141.     sprintf( szSemName, "\\SEM32\\PIPE\\SB2_PIPE%i", pib->pib_ulpid );
  4142.     if ( DosCreateEventSem( szSemName, &hevPipeGuard, 0L, 0L ) )
  4143.       AbortStartup();
  4144.  
  4145.     sprintf( szSemName, "\\SEM32\\SB2PIPE_T%i", pib->pib_ulpid );
  4146.     if ( DosCreateEventSem( szSemName, &hevTimed, 0, 0 ) ) AbortStartup();
  4147.     else _beginthread( TimedProcedure, aStack2, sizeof ( aStack2 ), NULL );
  4148.  
  4149.     sprintf( szSemName, "\\SEM32\\SB2PIPE_HT%i", pib->pib_ulpid );
  4150.     if ( DosCreateEventSem( szSemName, &hevHeavyTimed, 0, 0 ) ) AbortStartup();
  4151.     else _beginthread( HeavyTimedProcedure, aStack3, sizeof ( aStack3 ), NULL );
  4152.   }
  4153.  
  4154.   if ( argc > 1 ) pszIniFile = argv[1];
  4155.   else
  4156.   {
  4157.     pszIniFile = new char[strlen( argv[0] ) + 1];
  4158.     SB2_CfgFilename( pszIniFile, argv[0] );
  4159.   }
  4160.  
  4161.   ULONG ulWinStyle = FCF_AUTOICON | FCF_ICON | FCF_NOBYTEALIGN | FCF_TASKLIST;
  4162.  
  4163.   if ( ( hwPipeFrame = WinCreateStdWindow( HWND_DESKTOP, 0, &ulWinStyle,
  4164.     szClassName, 0, 0, NULLHANDLE, ICO_MAIN, &hwPipeClient ) ) == 0L )
  4165.     AbortStartup();
  4166.  
  4167.   if ( ! ( pPipeDesc = new DescWindow ) ) AbortStartup();
  4168.   else if ( ! pPipeDesc->CreateWindow( szDescClassName ) ) AbortStartup();
  4169.  
  4170.   WinSetWindowText( hwPipeFrame, "SysBar/2 Pipe Monitor" );
  4171.  
  4172. //  iSwCellSize[2] = WinQuerySysValue( HWND_DESKTOP, SV_CXICON ) + 2;
  4173.  
  4174.   {
  4175.     IniFile *pCfg = new IniFile( pszIniFile );
  4176.     int x = 0, y = 0, s = 0;
  4177.     if ( pCfg && ( *pCfg )() )
  4178.     {
  4179.       x = atoi2( pCfg->Get( szSysBar2Pipe, "x" ) );
  4180.       y = atoi2( pCfg->Get( szSysBar2Pipe, "y" ) );
  4181.       if ( ( s = atoi2( pCfg->Get( szSysBar2Pipe, "customsize" ) ) ) > 0 )
  4182.         iCellSize[3] = s;
  4183.       iLarge = atoi2( pCfg->Get( szSysBar2Pipe, "size" ) ) & 3;
  4184.       iBindToCorner = atoi2( pCfg->Get( szSysBar2Pipe, "cornerbind" ) );
  4185.       if ( iBindToCorner > 4 || iBindToCorner < 0 ) iBindToCorner = 0;
  4186.       iOrientation = atoi2( pCfg->Get( szSysBar2Pipe, "orientation" ) ) & 1;
  4187.       iTopmost = atoi2( pCfg->Get( szSysBar2Pipe, "topmost" ) ) & 3;
  4188.       bLockPosition = ( strcmp2(
  4189.         pCfg->Get( szSysBar2Pipe, "lockposition" ), pszYesNo[1] ) == 0 );
  4190.       char* s = pCfg->Get( szSysBar2Pipe, "cellcolor" );
  4191.       if ( s ) iDefaultBackColor = SB2_ColorA2I( s );
  4192.       s = pCfg->Get( szSysBar2Pipe, "textcolor" );
  4193.       if ( s ) iDefaultTextColor = SB2_ColorA2I( s );
  4194.       s = pCfg->Get( szNumberSection, szNumberDefault );
  4195.  
  4196.       LoadNumberOptions( s, &DefaultNumberOptions );
  4197.       LoadCellCfg( pCfg );
  4198.  
  4199.       char *p = pCfg->Get( szMiscSection, "week" );
  4200.       for ( int i = 0; p && i < iDaysOfTheWeek; i++ )
  4201.         p = SB2_ParseValue( p, szDaysOfTheWeek[i] );
  4202.       p = pCfg->Get( szMiscSection, "month" );
  4203.       for ( i = 0; p && i < iMonths; i++ ) p = SB2_ParseValue( p, szMonths[i] );
  4204.       for ( i = 0; i < iErrorCount; i++ )
  4205.         if ( ( p = pCfg->Get( szErrorSection, pszErrorIDs[i] ) ) && *p )
  4206.         {
  4207.           char *p2 = new char[strlen( p ) + 1];
  4208.           if ( p2 )
  4209.           {
  4210.             strcpy( p2, p );
  4211.             pszErrors[i] = p2;
  4212.           }
  4213.         }
  4214.     }
  4215.     SB2_LoadFontCfg( szDescFontSection, &fatDesc, pCfg );
  4216.     SB2_LoadFontCfg( szCellFontSection, &fatCell, pCfg );
  4217.  
  4218.     delete pCfg;
  4219.     if ( ! WinSetWindowPos( hwPipeFrame, HWND_TOP, x, y, 0, 0, SWP_MOVE ) )
  4220.       AbortStartup();
  4221.     else
  4222.     {
  4223.       ResizeWindow();
  4224.       WinPostMsg( hwPipeFrame, WM_COMMAND,
  4225.         ( MPARAM ) ( MNU_PIPE_BIND_OFF + iBindToCorner ), 0L );
  4226.     }
  4227.   }
  4228.  
  4229.   _beginthread( CheckStatus, aStack, sizeof ( aStack ), NULL );
  4230.  
  4231.   if ( ! iCellCount ) WinPostMsg( hwPipeClient, WM_COMMAND,
  4232.     ( MPARAM ) MNU_PIPE_PROPERTIES, 0 );
  4233.  
  4234.   while( WinGetMsg( hab, &qmsg, 0L, 0, 0 ) ) WinDispatchMsg( hab, &qmsg );
  4235.  
  4236.   if ( iIfmibSocket != -1 )
  4237.   {
  4238.     SoClose( iIfmibSocket );
  4239.     iIfmibSocket = -1;
  4240.   }
  4241.   if ( hmDosCall1 )
  4242.   {
  4243.     DosFreeModule( hmDosCall1 );
  4244.     dpsc = NULL;
  4245.     hmDosCall1 = NULLHANDLE;
  4246.   }
  4247.   if ( hmSo32DLL )
  4248.   {
  4249.     DosFreeModule( hmSo32DLL );
  4250.     hmSo32DLL = NULLHANDLE;
  4251.   }
  4252.   if ( hmTCP32DLL )
  4253.   {
  4254.     DosFreeModule( hmTCP32DLL );
  4255.     hmTCP32DLL = NULLHANDLE;
  4256.   }
  4257.  
  4258.   SB2_Over();
  4259.  
  4260.   delete pPipeDesc;
  4261.   WinDestroyWindow( hwPipeFrame );
  4262.   WinDestroyMsgQueue( hmq );
  4263.   WinTerminate( hab );
  4264.  
  4265.   if ( argc == 1 ) delete pszIniFile;
  4266.  
  4267.   return 0;
  4268. }
  4269.  
  4270.