home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / xp / xp_thrmo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  10.4 KB  |  345 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /* *
  20.  * 
  21.  *
  22.  * xp_thrmo.c --- Status message text for the thermometer.
  23.  */
  24.  
  25. #include "xp.h"
  26. #include "xp_thrmo.h"
  27. #include "xpgetstr.h"
  28. #include <ctype.h>
  29.  
  30. extern int XP_THERMO_BYTE_FORMAT;
  31. extern int XP_THERMO_KBYTE_FORMAT;
  32. extern int XP_THERMO_HOURS_FORMAT;
  33. extern int XP_THERMO_MINUTES_FORMAT;
  34. extern int XP_THERMO_SECONDS_FORMAT;
  35. extern int XP_THERMO_SINGULAR_FORMAT;
  36. extern int XP_THERMO_PLURAL_FORMAT;
  37. extern int XP_THERMO_PERCENTAGE_FORMAT;
  38. extern int XP_THERMO_UH;
  39. extern int XP_THERMO_PERCENT_FORM;
  40. extern int XP_THERMO_PERCENT_RATE_FORM;
  41. extern int XP_THERMO_RAW_COUNT_FORM;
  42. extern int XP_THERMO_BYTE_RATE_FORMAT;
  43. extern int XP_THERMO_K_RATE_FORMAT;
  44. extern int XP_THERMO_M_RATE_FORMAT;
  45. extern int XP_THERMO_STALLED_FORMAT;
  46. extern int XP_THERMO_RATE_REMAINING_FORM;
  47. extern int XP_THERMO_RATE_FORM;
  48.  
  49.  
  50. #define KILOBYTE        (1024L)
  51. #define MEGABYTE        (KILOBYTE * KILOBYTE)
  52. #define MINUTE            (60L)
  53. #define HOUR            (MINUTE * MINUTE)
  54.  
  55. #define BYTE_FORMAT         XP_GetString(XP_THERMO_BYTE_FORMAT)
  56. #define KILOBYTE_FORMAT     XP_GetString(XP_THERMO_KBYTE_FORMAT)
  57. #define MEGABYTE_FORMAT  XP_GetString(XP_THERMO_MBYTE_FORMAT)
  58.  
  59. #define BYTE_RATE_FORMAT    XP_GetString(XP_THERMO_BYTE_RATE_FORMAT)
  60. #define K_RATE_FORMAT        XP_GetString(XP_THERMO_K_RATE_FORMAT)
  61. #define M_RATE_FORMAT        XP_GetString(XP_THERMO_M_RATE_FORMAT)
  62. #define STALLED_FORMAT        XP_GetString(XP_THERMO_STALLED_FORMAT)
  63.  
  64. #define HOURS_FORMAT           XP_GetString(XP_THERMO_HOURS_FORMAT)
  65. #define MINUTES_FORMAT        XP_GetString(XP_THERMO_MINUTES_FORMAT)
  66. #define SECONDS_FORMAT        XP_GetString(XP_THERMO_SECONDS_FORMAT)
  67.  
  68. #define PERCENTAGE_FORMAT    XP_GetString(XP_THERMO_PERCENTAGE_FORMAT)
  69.  
  70. #define UH                    XP_GetString(XP_THERMO_UH)
  71.  
  72. #define IS_PLURAL(x)        (((x) == 1) ? "" : XP_GetString(XP_THERMO_PLURAL_FORMAT) )        /* L10N? */
  73.  
  74. #define    ENOUGH_TIME_TO_GUESS    5L /* #### customizable? */
  75.  
  76. #define RATE_REMAINING_FORM    XP_GetString(XP_THERMO_RATE_REMAINING_FORM)
  77. #define RATE_FORM                   XP_GetString(XP_THERMO_RATE_FORM)
  78. #define PERCENT_FORM               XP_GetString(XP_THERMO_PERCENT_FORM)
  79. #define PERCENT_RATE_FORM        XP_GetString(XP_THERMO_PERCENT_RATE_FORM)
  80. #define RAW_COUNT_FORM            XP_GetString(XP_THERMO_RAW_COUNT_FORM)
  81.  
  82. #define STALL_TIME                4L
  83.  
  84. /* Returns a text string to describe the current progress of some/all
  85.    transfers in progress.
  86.  
  87.    total_bytes        How many bytes we are waiting for, of all documents
  88.                     in progress.  If this is unknown, it should be 0.
  89.                     Note that if four documents are in progress, and
  90.                     the sizes of three are known and the size of one is
  91.                     unknown, then the total_bytes should be 0, since
  92.                     a single unknown makes the total unknown.
  93.  
  94.     bytes_received    How many bytes have been read so far.  If total_bytes
  95.                     is non-0, and this is larger than total_bytes, then
  96.                     there is a bug.
  97.  
  98.     start_time_secs    The time at which the transfer started, in seconds.
  99.  
  100.     now_secs        The current time, in seconds.  The 0-point of these
  101.                     values is uninteresting, only the relationship between
  102.                     The two.  It would be fine for start_time_secs to 
  103.                     always be 0, and now_secs to be the number of seconds
  104.                     since the transfer began.
  105.  
  106.   Returns: a statically allocated string, or NULL. NULL is returned in
  107.   out-of-memory conditions, or when there is nothing to say (as would
  108.   happen early in the transfer, if all values were 0.) DO NOT FREE THE
  109.   RETURNED STRING.
  110.  
  111.   The caller is responsible for freeing the returned string. */
  112.  
  113. const char*
  114. XP_ProgressText( unsigned long total_bytes,
  115.                  unsigned long bytes_received,
  116.                  unsigned long start_time_secs,
  117.                  unsigned long now_secs )
  118. {
  119.     /* This is all fairly hairy, but generating sensible human-readable text
  120.      always is.   Also, this doesn't internationalize very well... */
  121.     static char*    output = NULL;
  122.     static char*    scratch = NULL;
  123.     static unsigned long    last_secs = 0;
  124.     static unsigned long    last_bytes_received = 0;
  125.     static unsigned long    last_secs_left = -1;
  126.     static unsigned long    last_secs_received = 0;
  127.     static unsigned long    last_total = -1;
  128.     
  129.     XP_Bool            size_known = total_bytes > 0;
  130.     XP_Bool            stalled = FALSE;
  131.     
  132.     unsigned long    bytes_remaining = total_bytes - bytes_received;
  133. #if 0
  134.     float            fmegs_received = (float)bytes_received / (float)MEGABYTE;
  135.     unsigned long    delta_received = bytes_received - last_bytes_received;
  136.     long            delta_time = now_secs - last_secs;
  137. #endif
  138.     unsigned long    elapsed_time = now_secs - start_time_secs;
  139.  
  140.     float            bytes_per_sec = 0;
  141.     long            secs_left = -1;
  142.     long             how_long_since = 0;
  143.     
  144.     char*            brief_length;
  145.     char*            percent;            /* bytes_received / total_bytes */
  146.     char*            rate;                /* bytes_received / elapsed_time */        
  147.     char*            tleft;                /* bytes_remaining / rate */
  148.     
  149.     /* allocate our static buffers */
  150.     if ( !output )
  151.     {
  152.         output = (char*) XP_ALLOC( 300 ); /* what if this ain't enough? */
  153.         if ( !output )
  154.             return NULL;
  155.     }
  156.     if ( !scratch )
  157.     {
  158.         scratch = (char*) XP_ALLOC( 300 );
  159.         if ( !scratch )
  160.         {
  161.             XP_FREE( output );
  162.             output = NULL;
  163.             return NULL;
  164.         }
  165.     }    
  166.     /* scratch is just a buffer that we divide up for several different
  167.     purposes, instead of mallocing a few small chunks.  output is
  168.     the buffer that we eventually write into when combining these
  169.     various chunks together. */
  170.     brief_length = scratch;
  171.     percent = brief_length + 20;
  172.     rate = percent + 20;
  173.     tleft = rate + 100;
  174.  
  175.     /* key off of total_bytes and update statics when it changes */    
  176.     if ( total_bytes != last_total && total_bytes > 0 )
  177.     {
  178.         last_secs = 0;
  179.         last_bytes_received = 0;
  180.         last_secs_left = -1;
  181.         last_secs_received = 0;
  182.         last_total = total_bytes;
  183.     }
  184.     
  185.     if ( total_bytes < KILOBYTE )
  186.         sprintf( brief_length, BYTE_FORMAT, total_bytes );
  187.     else
  188.         sprintf( brief_length, KILOBYTE_FORMAT, total_bytes / KILOBYTE );
  189.     
  190.     /* boundary conditions */
  191.     if ( bytes_received <= 0 || start_time_secs <= 0 ||
  192.          start_time_secs >= now_secs ) 
  193.     {
  194.         *rate = 0;
  195.         *tleft = 0;
  196.     }
  197.     else
  198.     {
  199.         /* build rate and time left strings */
  200.  
  201.         if ( bytes_received < last_bytes_received )
  202.             last_bytes_received = bytes_received;
  203.             
  204.         if ( elapsed_time > 0 )
  205.             bytes_per_sec = ( (float)bytes_received / (float)elapsed_time );
  206.         else
  207.             bytes_per_sec = 0;
  208.             
  209.         if ( bytes_received == last_bytes_received && bytes_received != total_bytes )
  210.         {
  211.             how_long_since = now_secs - last_secs_received;
  212.             if ( how_long_since > STALL_TIME )
  213.                 stalled = TRUE;
  214.         }
  215.         else
  216.             last_secs_received = now_secs;
  217.             
  218.         /* someone is mixing the streams --- just bail.
  219.            this sucks
  220.            chouck 18-Sep-95
  221.          */
  222.         if ( bytes_per_sec < 0 )
  223.             return NULL;
  224.  
  225.         if ( elapsed_time < ENOUGH_TIME_TO_GUESS )
  226.             ;
  227.         else if (bytes_per_sec != 0)
  228.         {
  229.             secs_left = (long)( size_known ? ( (float)bytes_remaining / bytes_per_sec ) : 0);
  230.     
  231.             if ( secs_left > last_secs_left )
  232.                 secs_left = last_secs_left;        
  233.             else
  234.                 last_secs_left = secs_left;
  235.         }
  236.         
  237.         /* build rate string */
  238.         if ( elapsed_time < ENOUGH_TIME_TO_GUESS )
  239.             *rate = 0;
  240.         else if ( stalled )
  241.             sprintf( rate, STALLED_FORMAT );
  242.         else if ( bytes_per_sec < KILOBYTE )
  243.             sprintf( rate, BYTE_RATE_FORMAT, (long) bytes_per_sec );
  244.         else
  245.         {
  246.             double        tmp;
  247.             tmp = (double)bytes_per_sec / (double)KILOBYTE;    
  248.             sprintf( rate, K_RATE_FORMAT, tmp );
  249.         }
  250.  
  251.         /* build time left string */
  252.         if (    secs_left <= 0 ||
  253.                 elapsed_time < ENOUGH_TIME_TO_GUESS ||
  254.                 bytes_per_sec < KILOBYTE )
  255.             *tleft = 0;
  256.         else if ( secs_left >= HOUR )
  257.             sprintf( tleft, HOURS_FORMAT,
  258.                      secs_left / HOUR,
  259.                      (secs_left / MINUTE) % MINUTE,
  260.                      secs_left % MINUTE );
  261.         else if ( secs_left >= MINUTE )
  262.             sprintf( tleft, MINUTES_FORMAT, secs_left / MINUTE, secs_left % MINUTE );
  263.         else
  264.             sprintf( tleft, SECONDS_FORMAT, secs_left, IS_PLURAL( secs_left ) );
  265.     }
  266.     
  267.     /* build percentage string */
  268.     if ( size_known && total_bytes > 0 )
  269.     {
  270.         int p = ( bytes_received * 100 ) / total_bytes;
  271.         /* Allow it to get >100 so that we notice when netlib is lying to
  272.          us, but don't treat 99.8% as 100% because people look at the
  273.          100% and read "done" instead of "almost done" and wonder what
  274.          it's doing. */
  275.         if ( p >= 100 && ( bytes_received != total_bytes ) )
  276.             p = 99;
  277.         sprintf( percent, PERCENTAGE_FORMAT, p );
  278.     }
  279.     else
  280.     {
  281.         if ( bytes_received < KILOBYTE )
  282.             sprintf( percent, UH, bytes_received, IS_PLURAL( bytes_received ) );
  283.         else
  284.             sprintf( percent, KILOBYTE_FORMAT, bytes_received / KILOBYTE );
  285.     }
  286.     
  287.     
  288.     /* build output string */
  289.     if ( size_known )
  290.     {
  291.         if ( total_bytes )
  292.         {
  293.             if ( *tleft )
  294.             {
  295.                 /* "%s of %s (at %s, %s remaining)" */
  296.                 sprintf( output, RATE_REMAINING_FORM, percent, brief_length, rate, tleft );
  297.             }
  298.             else if ( *rate )
  299.             {
  300.                 /* "%s of %s (at %s)" */
  301.                 sprintf( output, RATE_FORM, percent, brief_length, rate );
  302.             }
  303.             else
  304.             {
  305.                 /* "%s of %s" */
  306.                 sprintf( output, PERCENT_FORM, percent, brief_length );
  307.             }
  308.         }
  309.     }
  310.     else if ( bytes_received > 0 )
  311.     {
  312.         if ( *rate )
  313.         {
  314.             /* "%s read (at %s)" */
  315.             sprintf( output, PERCENT_RATE_FORM, percent, rate );
  316.         }
  317.         else
  318.             sprintf( output, RAW_COUNT_FORM, percent );
  319.     }
  320.     else
  321.         *output = 0;
  322.     
  323. #if 0
  324.     XP_TRACE(( "\n" ));
  325.     XP_TRACE(( "know size:%d\n", size_known ));
  326.     XP_TRACE(( "total:%d rec:%d last_rec:%d\n", total_bytes, bytes_received, last_bytes_received));
  327.     XP_TRACE(( "now:%d last:%d lsr:%d\n", now_secs, last_secs, last_secs_received));
  328.     XP_TRACE(( "left:%d last_left:%d\n", secs_left, last_secs_left));
  329.     XP_TRACE(( "d:%d e:%d bps:%f\n", delta_time, elapsed_time, bytes_per_sec ));
  330.     XP_TRACE(( "ti:%d\n", how_long_since ));
  331. #endif
  332.  
  333.     last_secs = now_secs;
  334.     last_bytes_received = bytes_received;
  335.     
  336.     if ( *output )
  337.     {
  338.         return output;
  339.     }
  340.     else
  341.     {
  342.         return NULL;
  343.     }
  344. }
  345.