Changeset 5055


Ignore:
Timestamp:
10/16/12 06:26:29 (8 years ago)
Author:
paulf
Message:

new ewhtmlemail installment from Ruben, improved charts

Location:
trunk/src/reporting/ewhtmlemail
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/reporting/ewhtmlemail/ewhtmlemail.c

    r5049 r5055  
    2929 *    https://developers.google.com/chart/interactive/docs/reference/ 
    3030 *****************************************************************************/ 
    31 #define VERSION_STR "1.0.38 - October 5, 2012" 
     31#define VERSION_STR "1.0.40 - October 12, 2012" 
    3232 
    3333#define MAX_STRING_SIZE 1024    /* used for many static string place holders */ 
     
    5151#include <site.h> 
    5252#include <chron3.h> 
     53#include <gd.h> 
     54#include <gdfonts.h> 
    5355#ifndef _WINNT 
    5456#include <unistd.h> 
     
    6062 *********/ 
    6163#define MAX_STATIONS 200 
    62 #define MAX_GET_SAMP 700 
    63 #define MAX_GET_CHAR 2500 
     64#define MAX_GET_SAMP 1200               /* Number of samples in a google chart */ 
     65#define MAX_GET_CHAR 2500               /* Maximum number of characters in a google GET request */ 
     66#define MAX_POL_LEN 120000              /* Maximum number of samples in a trace gif */ 
    6467#define MAX_WAVE_SERVERS 10 
    6568#define MAX_ADDRESS 80 
     
    9396void status( unsigned char, short, char* ); 
    9497int process_message(HypoArc *arc, MAG_INFO *mag); 
    95 void GoogleMapRequest(char*, int*, SITE**, int, double, double); 
     98void GoogleMapRequest(char*, SITE**, int, double, double); 
    9699void GoogleChartRequest(char*, int*, double*, int, int, char, int); 
    97100char simpleEncode(int); 
    98 int getWSData(SITE*, double, double, double*, int); 
    99101int searchSite(char*, char*, char*, char*); 
    100 char* getWSErrorStr(int errorCode, char* msg); 
     102char* getWSErrorStr( int, char* ); 
     103int getWStrbf( char*, int*, SITE*, double, double ); 
     104int trbufresample( int*, int, char*, int, double, double, int ); 
     105double fbuffer_add( double*, int, double ); 
     106int makeGoogleChart( char*, int*, int, char, int, int, int ); 
     107void gdImagePolyLine( gdImagePtr, gdPointPtr, int, int ); 
     108int trbf2gif( char*, int, gdImagePtr, double, double, int, int ); 
     109int pick2gif(gdImagePtr, double, char, double, double, int); 
     110                 
    101111 
    102112/* Globals 
     
    125135static int        nwaveservers = 0;       // Number of waveservers 
    126136static int        nemailrecipients = 0;   // Number of email recipients 
    127 static double     TimeMargin = 10.;        // Margin to download samples. 
    128 static double     DurationMax = 144.;        // Maximum duration to show., truncate to this if greater (configurable) 
     137static double     TimeMargin = 10;        // Margin to download samples. 
     138static double     DurationMax = 144.;     // Maximum duration to show., truncate to this if greater (configurable) 
    129139static int        UseBlat = 0;        // use blat syntaxi as the mail program instead of a UNIX like style 
    130140static char       BlatOptions[MAX_STRING_SIZE];      // apply any options needed after the file....-server -p profile etc... 
     
    138148static time_t     last_qid_time = 0;  // last qid at time  
    139149static int        qid_counter = 0;  // counter for qids in queue awaiting MLs 
     150 
     151/* RSL: 2012.10.10 Gif options */ 
     152static int                UseGIF = 0;            // Use GIF files instead of google charts 
     153static int        TraceWidth = 600;        // Width of the GIF files 
     154static int        TraceHeight = 61;        // Height of the GIF files 
    140155 
    141156// Array of waveservers 
     
    626641            TimeMargin = k_val(); 
    627642         } 
    628          else if ( k_its("MaxDuration") )  
    629          { 
    630             DurationMax = k_val(); 
    631          } 
    632643         else if ( k_its("WaveServer") ) 
    633644         { 
     
    657668                UseUTC = 1; 
    658669         } 
     670         else if ( k_its("MaxDuration") )  
     671          { 
     672             DurationMax = k_val(); 
     673          } 
    659674         else if ( k_its("MagWaitSeconds") ) 
    660675         { 
     
    668683         { 
    669684                ShowDetail = 1; 
    670          } 
     685             } 
     686             else if ( k_its("UseGIF") ) 
     687         { 
     688                    UseGIF = 1; 
     689             } 
     690             else if ( k_its("TraceWidth") )  
     691         { 
     692            TraceWidth = k_val(); 
     693         } 
     694             else if ( k_its("TraceHeight") )  
     695         { 
     696            TraceHeight = k_val(); 
     697         } 
    671698         else if ( k_its("EmailRecipient") ) 
    672699         { 
     
    829856 ******************************************************************************/ 
    830857int process_message(HypoArc * arc, MAG_INFO *mag) { 
     858 
     859        double          starttime = 0;                                  /* Start time for all traces */ 
     860        double          endtime = 0;                                    /* End time for all traces */ 
     861        double          dur;                                                    /* Duration of the traces */ 
     862        int             i, pos;                                                 /* Generic counters */ 
     863        int             gsamples[MAX_GET_SAMP];                 /* Buffer for resampled traces */ 
     864        char            chartreq[5000];                                 /* Buffer for chart requests or GIFs */ 
     865        char            cp[1000000];                                    /* Buffer to hold the html message */ 
     866        SITE            *sites[MAX_STATIONS];                   /* Selected sites */ 
     867        char            phases[MAX_STATIONS];                   /* Phase types of each trace */ 
     868        double          arrivalTimes[MAX_STATIONS];             /* Arrival times of each trace */ 
     869        int                     coda_lengths[MAX_STATIONS];             /* Coda lengths of each trace */ 
     870        double          coda_mags[MAX_STATIONS];                /* station coda mags > 0 if used */ 
     871        int                     weights[MAX_STATIONS];                  /* Weight codes for each trace */ 
     872        double          distances[MAX_STATIONS];                /* Distance from each station */ 
     873        struct tm * (*timefunc)(const time_t *); 
     874        int                     codaLen;                                                /* Holds the coda length absolute */ 
     875        int                     nsites = 0;                                             /* Number of stations in the arc msg */ 
     876        char            system_command[MAX_STRING_SIZE];/* System command to call email prog */ 
     877        char            kml_filename[MAX_STRING_SIZE];  /* Name of kml file to be generated */ 
     878        FILE            *cssfile;                                               /* CSS File to be embedded in email */ 
     879        FILE            *htmlfile;                                              /* HTML file */ 
     880        FILE            *header_file;                                   /* Email header file */ 
     881        char            ch; 
     882        time_t          ot, st;                                                 /* Times */ 
     883        struct tm       *timeinfo; 
     884        char            timestr[80];                                    /* Holds time messages */ 
     885        char            fullFilename[250];                              /* Full html file name */ 
     886        char            hdrFilename[250];                               /* Full header file name */ 
     887        char            time_type[30];                                  /* Time type UTC or local */ 
     888        char            *buffer;                                                /* Buffer for raw tracebuf2 messages */ 
     889        int                     bsamplecount = MAX_SAMPLES * 4; /* Length of buffer */ 
     890        char            giffilename[256];                               /* Name of GIF files */ 
     891        gdImagePtr      gif;                                                    /* Pointer for GIF image */ 
     892        FILE            *giffile;                                               /* GIF file */ 
     893        int                     BACKCOLOR;                                              /* Background color of GIF images */ 
     894        int                     TRACECOLOR;                                             /* Trace color in GIF images */ 
     895        int                     PICKCOLOR;                                              /* Pick color in GIF images */ 
    831896    
    832    double starttime = 0; 
    833    double endtime = 0; 
    834  
    835   
    836    int i, pos;                /* Generic counters */ 
    837    double *trace;                   /* Traces to be plotted */ 
    838    int nsamples = MAX_GET_SAMP;  /* Number of samples in each trace */ 
    839    char cp[1000000];    /* Buffer to hold the message */ 
    840    SITE *sites[MAX_STATIONS];    //Holds the selected sites 
    841    char phases[MAX_STATIONS];    //Holds the phase types 
    842    double arrivalTimes[MAX_STATIONS]; //Holds the arrival times 
     897 
     898 
     899        /* Initialize kml file name and time type 
     900         ****************************************/ 
     901        kml_filename[0] = 0; 
     902        strcpy( time_type, "Local Time" ); 
     903        starttime = arc->sum.ot; 
    843904    
    844    int coda_lengths[MAX_STATIONS]; // Coda lengths 
    845    double coda_mags[MAX_STATIONS]; // station coda mags > 0 if used 
    846    int weights[MAX_STATIONS]; // Weight codes 
    847    double distances[MAX_STATIONS]; // Distance 
    848    struct tm * (*timefunc)(const time_t *); 
    849     
    850    int codaLen;                      //Holds the coda length absolute 
    851    int nsites = 0; 
    852    char system_command[MAX_STRING_SIZE]; 
    853    char kml_filename[MAX_STRING_SIZE]; 
    854     
    855    FILE *cssfile; 
    856    FILE *htmlfile; 
    857    FILE *header_file; 
    858    char ch; 
    859    char req[MAX_GET_CHAR]; 
    860    int  nreq = 0; 
    861     
    862    time_t ot, st; 
    863    int dur; 
    864    struct tm *timeinfo; 
    865    char timestr[80]; 
    866    char fullFilename[250]; 
    867    char hdrFilename[250]; 
    868    char time_type[30]; 
    869     
    870  
    871    kml_filename[0] = 0; 
    872    strcpy(time_type, "Local Time"); 
    873     
    874    starttime = arc->sum.ot; 
    875     
    876  
    877    /* Read phases using another read_arc.c function  
    878     ***********************************************/ 
    879    for (i=0; i< arc->num_phases; i++) 
    880    { 
    881       if (strlen(arc->phases[i]->site)==0) 
    882          continue; 
    883           
    884       pos = searchSite(arc->phases[i]->site, arc->phases[i]->comp, arc->phases[i]->net, arc->phases[i]->loc); 
    885       if (pos == -1) 
    886       { 
    887          logit("et", "ewhtmlemail: Unable to find %s.%s.%s.%s on the site file\n",  
    888             arc->phases[i]->site, arc->phases[i]->comp, arc->phases[i]->net, arc->phases[i]->loc); 
    889          continue; 
    890       }       
     905 
     906        /* Read phases using read_arc.c function 
     907         * For each phase, try to find the station in the sites file 
     908         * Then store phase data (arrival, type, coda length, etc) 
     909         * and update starttime and endtime to include all phases 
     910         * and corresponding coda lengths. 
     911         ***********************************************************/ 
     912        for (i=0; i< arc->num_phases; i++) 
     913        { 
     914                //If this phase does not have a site, continue to next 
     915                if( strlen( arc->phases[i]->site ) == 0 ) 
     916                        continue; 
     917         
     918                // Search this site on the sites file 
     919                pos = searchSite( arc->phases[i]->site,  
     920                                arc->phases[i]->comp, 
     921                                arc->phases[i]->net, 
     922                                arc->phases[i]->loc) ; 
     923                // If site is not found, continue to next phase 
     924                if( pos == -1 ) 
     925                { 
     926                        logit( "et", "ewhtmlemail: Unable to find %s.%s.%s.%s on the site file\n",  
     927                        arc->phases[i]->site, 
     928                        arc->phases[i]->comp, 
     929                        arc->phases[i]->net, 
     930                        arc->phases[i]->loc ); 
     931                        continue; 
     932                }       
    891933       
    892934       
    893       /* New station, store its pointer 
    894        ********************************/ 
    895       sites[nsites] = &Site[pos]; 
     935                // New station, store its pointer 
     936                sites[nsites] = &Site[pos]; 
     937                 
     938                 
     939                // Select phase type and arrival time 
     940                if( arc->phases[i]->Plabel == 'P' || arc->phases[i]->Ponset == 'P' ) 
     941                { 
     942                        phases[nsites] = 'P'; // Store phase type 
     943                        arrivalTimes[nsites] = arc->phases[i]->Pat - GSEC1970; // Store arrival time 
     944                        weights[nsites] = arc->phases[i]->Pqual; // Store weight 
     945                } 
     946                else // If not a P phase, assume its an S phase. Non P or S phases are assumed S 
     947                { 
     948                        phases[nsites] = 'S'; // Store phase type 
     949                        arrivalTimes[nsites] = arc->phases[i]->Sat - GSEC1970; // Store arrival time 
     950                        weights[nsites] = arc->phases[i]->Squal; // Store weight 
     951                } 
     952                 
     953                 
     954                // Store epicentral distance 
     955                distances[nsites] = arc->phases[i]->dist; 
     956                 
     957                 
     958                // Store coda duration 
     959                coda_lengths[nsites] = arc->phases[i]->codalen; 
     960                 
     961                 
     962                /* Md from channel for highest quality */ 
     963                if( arc->phases[i]->codawt == 0 ) 
     964                { 
     965                        coda_mags[nsites] = arc->phases[i]->Md; 
     966                } 
     967                else 
     968                { 
     969                        coda_mags[nsites] = 0.0; 
     970                } 
     971 
     972                // Increment nsites 
     973                nsites++; 
     974                 
     975                 
     976                /* Update endtime 
     977                 * Takes the last time instant of the latest event, defined as 
     978                 * the arrival time + coda length to set the overall endtime 
     979                 *************************************************************/ 
     980                codaLen = arc->phases[i]->codalen; 
     981                 
     982                // Negative codas are made positive 
     983                if (codaLen<0) codaLen = -codaLen; 
     984                 
     985                // For an unknown reason, sometimes the coda length is 599s 
     986                // Hence it is necessary to limit the coda length to 144 seconds  
     987                // to avoid long traces 
     988                codaLen = ( codaLen > 144 )?144:codaLen; 
     989                if( Debug ) 
     990                        logit( "o", "Coda length for %s.%s.%s.%s : %d\n",  
     991                                        arc->phases[i]->site, 
     992                                        arc->phases[i]->comp, 
     993                                        arc->phases[i]->net,  
     994                                        arc->phases[i]->loc, 
     995                                        arc->phases[i]->codalen); 
     996          
     997                // For the endtime definition, it is necessary to decide 
     998                // which P or S phase will be used. In this case, the latest one. 
     999                if( ( arc->phases[i]->Pat + codaLen ) > endtime )               //using P arrival or 
     1000                        endtime = arc->phases[i]->Pat + codaLen;                        // 
     1001                if( ( arc->phases[i]->Sat + codaLen ) > endtime )               //using S arrival 
     1002                        endtime = arc->phases[i]->Sat + codaLen; 
     1003          
     1004 
     1005                /* Check if the number of sites exceeds the 
     1006                 * predefined maximum number of stations 
     1007                 ******************************************/ 
     1008                if( nsites >= MAX_STATIONS )  
     1009                { 
     1010                        logit( "et", "ewhtmlemail: More than %d stations in message\n", 
     1011                                        MAX_STATIONS ); 
     1012                        break; 
     1013                } 
     1014        } // End of 'for' cycle for processing the phases in the arc message 
     1015 
     1016    
     1017        /* Correct times for epoch 1970 
     1018         ******************************/ 
     1019        starttime -= GSEC1970;          // Correct for epoch 
     1020        starttime -= TimeMargin;        // Add time margin 
     1021        endtime -= GSEC1970;            // Correct for epoch 
     1022        endtime += TimeMargin;          // Add time margin 
     1023 
     1024        /* Check maximum duration of the traces 
     1025         **************************************/ 
     1026        dur = endtime - starttime; 
     1027        if( dur > ( double ) DurationMax )  
     1028        { 
     1029        if( Debug ) logit( "ot", "Waveform Durations %d greater " 
     1030                        "than set by MaxDuration %d\n",  
     1031                                (int) (endtime - starttime), (int)DurationMax); 
     1032        endtime = starttime+DurationMax; 
     1033        dur = DurationMax;      /* this is used later for header of waveform table */ 
     1034        } 
     1035         
     1036        /* Change to UTC time, if required 
     1037         *********************************/ 
     1038        timefunc = localtime; 
     1039        if( UseUTC ) 
     1040        {  
     1041                timefunc = gmtime; 
     1042                strcpy( time_type, "UTC" ); 
     1043        } 
     1044         
     1045        /* Log debug info 
     1046         ****************/ 
     1047        if( Debug ) 
     1048        { 
     1049                logit("o", "Available channels:\n"); 
     1050                for( i = 0; i < nsites; i++ ) 
     1051                        logit( "o", "%5s.%3s.%2s.%2s\n", 
     1052                                        sites[i]->name, sites[i]->comp, 
     1053                                        sites[i]->net, sites[i]->loc); 
     1054             
     1055                logit( "o", "Time margin: %f\n", TimeMargin ); 
    8961056       
    897       /* Select phase type and arrival time 
    898        ************************************/ 
    899       if (arc->phases[i]->Plabel == 'P' || arc->phases[i]->Ponset == 'P') 
    900       { 
    901          phases[nsites] = 'P'; 
    902          arrivalTimes[nsites] = arc->phases[i]->Pat - GSEC1970; 
    903          weights[nsites] = arc->phases[i]->Pqual; 
    904       } 
    905       else 
    906       { 
    907          phases[nsites] = 'S'; 
    908          arrivalTimes[nsites] = arc->phases[i]->Sat - GSEC1970; 
    909          weights[nsites] = arc->phases[i]->Squal; 
    910       } 
    911       /* epicentral distance */ 
    912       distances[nsites] = arc->phases[i]->dist; 
     1057                ot = ( time_t ) starttime; 
     1058                timeinfo = timefunc ( &ot ); 
     1059                strftime( timestr, 80, "%Y.%m.%d %H:%M:%S", timeinfo ); 
     1060                logit( "o", "Waveform starttime: %s %s\n", timestr, time_type ); 
    9131061       
    914       /* Set coda duration */ 
    915       coda_lengths[nsites] = arc->phases[i]->codalen; 
    916  
    917       /* Md from channel for highest quality */ 
    918       if(arc->phases[i]->codawt == 0) { 
    919          coda_mags[nsites] = arc->phases[i]->Md; 
    920       } else { 
    921          coda_mags[nsites] = 0.0; 
    922       } 
    923        
    924       nsites++; 
    925        
    926            
    927       /* Update endtime 
    928        ****************/ 
    929       codaLen = arc->phases[i]->codalen; 
    930       if (codaLen<0) codaLen = -codaLen; 
    931        
    932       if (Debug) 
    933          logit("o", "Coda length: %d\n", arc->phases[i]->codalen); 
    934           
    935       if ((arc->phases[i]->Pat + codaLen) > endtime)   //using P arrival or 
    936          endtime = arc->phases[i]->Pat + codaLen;       // 
    937       if ((arc->phases[i]->Sat + codaLen) > endtime)   //using S arrival 
    938          endtime = arc->phases[i]->Sat + codaLen; 
    939           
    940  
    941       if (nsites >= MAX_STATIONS)  
    942       { 
    943          logit("et", "ewhtmlemail: More than %d stations in message\n", MAX_STATIONS); 
    944          break; 
    945       } 
    946    } 
    947  
    948     
    949    /* Correct times for epoch 1970 
    950     ******************************/ 
    951    starttime -= GSEC1970; 
    952    starttime -= TimeMargin; 
    953    endtime -= GSEC1970; 
    954    endtime += TimeMargin; 
    955  
    956    dur = endtime-starttime; 
    957    if ((double) dur > DurationMax) { 
    958        endtime = starttime+DurationMax; 
    959        if (Debug) logit("ot", "Waveform Durations %d greater than set by MaxDuration %d\n", (int) dur, (int)DurationMax); 
    960        dur = DurationMax;       /* this is used later for header of waveform table */ 
    961    } 
    962     
    963    timefunc = localtime; 
    964    if (UseUTC) {  
    965        timefunc = gmtime; 
    966        strcpy (time_type, "UTC"); 
    967    } 
    968    if (Debug) 
    969    { 
    970       logit("o", "Available channels:\n"); 
    971       for (i=0; i<nsites; i++) 
    972          logit("o", "%5s.%3s.%2s.%2s\n", 
    973             sites[i]->name, sites[i]->comp, 
    974             sites[i]->net, sites[i]->loc); 
    975              
    976       logit("o", "Time margin: %f\n", TimeMargin); 
    977        
    978       ot = (time_t)starttime; 
    979       timeinfo = timefunc ( &ot); 
    980       strftime (timestr,80,"%Y.%m.%d %H:%M:%S",timeinfo); 
    981       logit("o", "Waveform starttime: %s %s\n", timestr, time_type); 
    982        
    983       ot = (time_t)endtime; 
    984       timeinfo = timefunc ( &ot); 
    985       strftime (timestr,80,"%Y.%m.%d %H:%M:%S",timeinfo); 
    986       logit("o", "Waveform endtime:   %s %s\n", timestr, time_type); 
    987    } 
     1062                ot = ( time_t ) endtime; 
     1063                timeinfo = timefunc ( &ot ); 
     1064                strftime( timestr, 80, "%Y.%m.%d %H:%M:%S", timeinfo ); 
     1065                logit( "o", "Waveform endtime:   %s %s\n", timestr, time_type ); 
     1066        } 
    9881067    
    9891068    
    990    /* Allocate memory for trace 
    991     ***************************/ 
    992    trace = (double*) malloc(MAX_SAMPLES * sizeof(int)); 
    993    if (trace==NULL) 
    994    { 
    995       logit("e", "ewhtmlemail: Unable to alocate memory for processed traces\n"); 
    996       exit(-1); 
    997    } 
    998     
    999    /* build a KML file */ 
    1000    if (KMLdir[0] != 0) { 
    1001          logit("ot", "ewhtmlemail: writing KML file.\n"); 
    1002          kml_writer(KMLdir, &(arc->sum), KMLpreamble, kml_filename, sites, nsites); 
    1003    } 
    1004        
    1005    /* Start html email file 
    1006     ***********************/ 
    1007    sprintf(fullFilename, "%s_%ld.html", HTMLFile, arc->sum.qid ); 
    1008    if (Debug) logit("ot", "Creating html file %s\n", fullFilename); 
    1009  
    1010    if (htmlfile = fopen(fullFilename, "w")) 
    1011    { 
    1012       /* Save file header 
    1013        ******************/ 
    1014       if (strlen(EmailProgram)>0) 
    1015       { 
    1016          if (Debug) logit("ot", "Writing file header\n", fullFilename); 
    1017          /* fprintf(htmlfile, "Content-Type: text/html\n"); */ 
    1018          fprintf(htmlfile, "<html>\n<head>\n<style type=\"text/css\">"); 
    1019          if (Debug) 
    1020             logit("o", "Subject: ewAlert - Event ID: %d\nContent-Type: text/html\n", arc->sum.qid); 
    1021       } 
    1022        
     1069        /* At this point, we have retrieved the information required for the html email 
     1070         * traces, if there is any. Now, move forward to start producing the output files. 
     1071         *********************************************************************************/ 
     1072 
     1073 
     1074        /* build a KML file 
     1075         ******************/ 
     1076        if( KMLdir[0] != 0 ) 
     1077        { 
     1078                logit( "ot", "ewhtmlemail: writing KML file.\n" ); 
     1079                kml_writer( KMLdir, &(arc->sum), KMLpreamble, kml_filename, sites, nsites ); 
     1080        } 
     1081         
     1082         
     1083        /* Start html email file 
     1084         ***********************/ 
     1085        sprintf(fullFilename, "%s_%ld.html", HTMLFile, arc->sum.qid ); // Name of html file 
     1086        if( Debug ) logit( "ot", "Creating html file %s\n", fullFilename ); 
     1087 
     1088        // Open html file 
     1089        if( htmlfile = fopen( fullFilename, "w" ) ) 
     1090        { 
     1091                /* Save html header 
     1092                 ******************/ 
     1093                if( Debug ) logit( "ot", "Writing html header\n", fullFilename ); 
     1094                // Placing css in the html body instead of header, to bypass some email clients 
     1095                // blocking the style sheet 
     1096                fprintf( htmlfile, "<html>\n<body>\n<style type=\"text/css\">" ); 
    10231097          
    1024       /* Copy content of css file to html file 
    1025       ***************************************/    
    1026       if (strlen(StyleFile)>0)  
    1027        
    1028          if (Debug) logit("ot", "Copying css file to html header: %s\n", StyleFile); 
    1029          if (cssfile=fopen(StyleFile,"r")) 
    1030          { 
    1031          while(!feof(cssfile))  
    1032          { 
    1033             ch = getc(cssfile); 
    1034             if(ferror(cssfile)) 
    1035             { 
    1036                if (Debug) logit("e","Read css error\n"); 
    1037                clearerr(cssfile); 
    1038                break; 
    1039             } 
    1040             else 
    1041             { 
    1042                if(!feof(cssfile)) putc(ch, htmlfile); 
    1043                if(ferror(htmlfile)) 
    1044                { 
    1045                   if (Debug) logit("e","Write css error\n"); 
    1046                   clearerr(htmlfile); 
    1047                   break; 
    1048                } 
    1049             } 
    1050          } 
    1051          fclose(cssfile); 
    1052          } 
    1053          else 
    1054          { 
    1055             logit("et","Unable to open css file\n"); 
    1056          } 
    1057       } 
     1098                /* Copy content of css file to html file 
     1099                ***************************************/    
     1100                if( strlen( StyleFile ) > 0 ) // Check if there is a style file at all 
     1101                 
     1102                        if( Debug ) logit( "ot", "Copying css file to html header: %s\n", StyleFile ); 
     1103                        if( cssfile = fopen( StyleFile, "r" ) ) 
     1104                        { 
     1105                                while( !feof( cssfile ) )  
     1106                                { 
     1107                                        ch = getc(cssfile); 
     1108                                        if( ferror( cssfile ) ) 
     1109                                        { 
     1110                                                if( Debug ) logit( "e", "Read css error\n" ); 
     1111                                                clearerr( cssfile ); 
     1112                                                break; 
     1113                                        } 
     1114                                        else 
     1115                                        { 
     1116                                                if( !feof( cssfile ) ) putc( ch, htmlfile ); 
     1117                                                if( ferror( htmlfile ) ) 
     1118                                                { 
     1119                                                        if( Debug ) logit( "e", "Write css error\n" ); 
     1120                                                        clearerr( htmlfile ); 
     1121                                                        break; 
     1122                                                } 
     1123                                        } 
     1124                                } 
     1125                                fclose(cssfile); 
     1126                        } 
     1127                        else 
     1128                        { 
     1129                                logit("et","Unable to open css file\n"); 
     1130                        } 
     1131                } 
    10581132       
    10591133       
    1060       /* Close html header 
    1061        *******************/ 
    1062       fprintf(htmlfile, "\n</style>\n</head>\n"); 
     1134                /* Close style header 
     1135                 ********************/ 
     1136                fprintf( htmlfile, "\n</style>\n" ); 
    10631137       
    10641138       
    1065       /* Start email body 
    1066        ******************/ 
    1067       if (Debug) logit("ot", "Starting html body\n"); 
    1068       fprintf(htmlfile, "<body>\n"); 
     1139                /* Create table with reference information 
     1140                 *****************************************/ 
     1141                ot = ( time_t )( arc->sum.ot - GSEC1970 ); 
     1142                timeinfo = timefunc ( &ot ); 
     1143                strftime( timestr, 80, "%Y.%m.%d %H:%M:%S", timeinfo ); // Prepare origin time 
     1144                 
     1145                // Table header 
     1146                fprintf( htmlfile, "<table id=\"DataTable\">\n" ); 
     1147                 
     1148                // Event ID 
     1149                fprintf( htmlfile, "<tr><th>EW Event ID: %ld<th><tr>\n", arc->sum.qid ); 
     1150                 
     1151                // Origin time 
     1152                fprintf( htmlfile, "<tr class=\"alt\"><td>Origin time</td><td>%s %s</td><tr>\n", 
     1153                                timestr, time_type ); 
     1154                                 
     1155                // Latitude 
     1156                fprintf( htmlfile, "<tr><td>Latitude:</td><td>%7.4f</td><tr>\n", arc->sum.lat ); 
     1157                 
     1158                // Longitude 
     1159                fprintf( htmlfile, "<tr class=\"alt\"><td>Longitude:</td><td>%8.4f</td><tr>\n", 
     1160                                arc->sum.lon ); 
     1161                                 
     1162                // Depth 
     1163                fprintf( htmlfile, "<tr><td>Depth:</td><td>%4.1f km</td><tr>\n", arc->sum.z ); 
     1164                 
     1165                // Coda magnitude 
     1166                fprintf( htmlfile, "<tr class=\"alt\"><td>Coda Magnitude:</td>" 
     1167                                "<td>%4.1f %s nobs=%d</td><tr>\n",  
     1168                                arc->sum.Mpref, MAG_TYPE_STRING, (int) arc->sum.mdwt ); 
     1169                                 
     1170                // Optional amplitude magnitude 
     1171                if( UseML && mag != NULL ) 
     1172                { 
     1173                        fprintf( htmlfile, "<tr class=\"alt\"><td><a href=\"#ML\">Local Magnitude:" 
     1174                                        "</a></td><td>%4.1f &plusmn;%3.1f %s nobs=%d</td><tr>\n",  
     1175                                        mag->mag, mag->error, MAG_MSG_TYPE_STRING, mag->nchannels ); 
     1176                } 
     1177                 
     1178                /* Event details 
     1179                 ***************/ 
     1180                if( ShowDetail ) 
     1181                { 
     1182                        char Quality; 
     1183                         
     1184                        // RMS 
     1185                        fprintf( htmlfile, "<tr><td>RMS Error:</td><td>%5.2f s</td><tr>\n",  
     1186                                        arc->sum.rms); 
     1187                                         
     1188                        // Horizontal error 
     1189                        fprintf( htmlfile, "<tr class=\"alt\"><td>Horizontal Error:" 
     1190                                        "</td><td>%5.2f km</td><tr>\n", arc->sum.erh ); 
     1191                                         
     1192                        // Vertical error 
     1193                        fprintf( htmlfile, "<tr><td>Depth Error:</td><td>%5.2f km</td><tr>\n",  
     1194                                        arc->sum.erz ); 
     1195                                         
     1196                        // Azimuthal gap 
     1197                        fprintf( htmlfile, "<tr class=\"alt\"><td>Azimuthal Gap:</td>" 
     1198                                        "<td>%d Degrees</td><tr>\n", arc->sum.gap ); 
     1199                                         
     1200                        // Number of phases 
     1201                        fprintf( htmlfile, "<tr><td>Total Phases:</td><td>%d</td><tr>\n", 
     1202                                        arc->sum.nphtot); 
     1203                         
     1204                        // Used phases 
     1205                        fprintf( htmlfile, "<tr class=\"alt\"><td>Total Phases Used:</td>" 
     1206                                        "<td>%d</td><tr>\n", arc->sum.nph ); 
     1207                         
     1208                        // Number of S phases 
     1209                        fprintf( htmlfile, "<tr><td>Num S Phases Used:</td><td>%d</td><tr>\n", 
     1210                                        arc->sum.nphS ); 
     1211                                         
     1212                        // Average quality 
     1213                        Quality = ComputeAverageQuality( arc->sum.rms, arc->sum.erh, arc->sum.erz,  
     1214                                        arc->sum.z, (float) (1.0*arc->sum.dmin), arc->sum.nph, arc->sum.gap ); 
     1215                        fprintf(htmlfile, "<tr class=\"alt\"><td>Quality:</td>" 
     1216                                        "<td>%c</td><tr>\n", Quality); 
     1217                } 
     1218                 
     1219                // Finish reference table 
     1220                fprintf( htmlfile, "</table><br><br>\n" ); 
     1221          
     1222          
     1223          
     1224                /* Produce google map with the stations and hypocenter 
     1225                 *****************************************************/ 
     1226                if( Debug ) logit( "ot", "Computing Google map\n" ); 
     1227                GoogleMapRequest( chartreq, sites, nsites, arc->sum.lat, arc->sum.lon ); 
     1228                fprintf(htmlfile, "%s\n<br><br>", chartreq); 
     1229                 
     1230                 
     1231       
     1232                /* Reserve memory buffer for raw tracebuf messages 
     1233         *************************************************/ 
     1234                buffer = ( char* ) malloc( bsamplecount ); 
     1235                if( buffer == NULL ) 
     1236                { 
     1237                        logit( "et", "ewhtmlemail: Cannot allocate buffer for trace\n" ); 
     1238                        // return -1; - Event if there is no memory for traces, still try to send email 
     1239                } 
     1240                else 
     1241                { 
     1242                 
     1243                 
     1244                        /* Produce station traces 
     1245                         ************************/ 
     1246                        if( Debug ) logit("ot", "Computing Traces\n" ); 
     1247                         
     1248                        // Save header of traces table 
     1249                        st = ( time_t ) starttime; 
     1250                        timeinfo = timefunc( &st ); 
     1251                        strftime( timestr, 80, "%Y.%m.%d %H:%M:%S", timeinfo );  
     1252                        fprintf( htmlfile, "<table id=\"WaveTable\">\n" );  
     1253                        fprintf( htmlfile, "<tr><th>Waveforms: (StartTime: %s Duration: %d" 
     1254                                        " seconds)</th></tr>\n", timestr, (int) dur ); 
     1255                         
     1256                         
     1257                        /* Cycle for each station 
     1258                         *  - Try to retrieve waveform data from the wave servers 
     1259                         *  - Decide to produce GIF or google chart 
     1260                         *  - If GIF, call function to produce GIF file and the request is 
     1261                         *          the filename within <img> tags 
     1262                         *  - If google char, resample the data and then produce the google chart 
     1263                         *          encoded GET request 
     1264                         ************************************************************************/ 
     1265                        for( i = 0; i < nsites; i++ ) 
     1266                        { 
     1267          
     1268                                /* Load data from waveservers 
     1269                                 ****************************/ 
     1270                                if( !getWStrbf( buffer, &bsamplecount, sites[i], starttime, endtime ) ) 
     1271                                { 
     1272                                        logit( "t", "ewhtmlemail: Unable to retrieve data from waveserver" 
     1273                                                        " for trace from %s.%s.%s.%s\n", 
     1274                                                        sites[i]->name, sites[i]->comp, 
     1275                                                        sites[i]->net, sites[i]->loc ); 
     1276                                        continue; 
     1277                                } 
     1278                                 
     1279                                 
     1280                                /* Produce traces GIF or google chart 
     1281                                 ************************************/ 
     1282                                if( UseGIF ) 
     1283                                { 
     1284                                 
     1285                                        /* Produce GIF image 
     1286                                         *******************/ 
     1287                                        gif = gdImageCreate( TraceWidth, TraceHeight ); // Creates base image 
     1288                                 
     1289                                        // Set colors for the trace and pick 
     1290                                        BACKCOLOR = gdImageColorAllocate( gif, 255, 255, 255 ); // White 
     1291                                        TRACECOLOR = gdImageColorAllocate( gif, 0, 0, 96 );             // Dark blue 
     1292                                        PICKCOLOR = gdImageColorAllocate( gif, 96, 0, 0 );              // Dark red 
     1293                     
     1294                     
     1295                                        /* Plot trace 
     1296                                         ************/ 
     1297                                        if( trbf2gif( buffer, bsamplecount, gif, 
     1298                                                        starttime, endtime, TRACECOLOR, BACKCOLOR ) ) 
     1299                                        { 
     1300                                                if( Debug ) logit( "o", "Created gif image for trace " 
     1301                                                                "from %s.%s.%s.%s\n", 
     1302                                                                sites[i]->name, sites[i]->comp, 
     1303                                                                sites[i]->net, sites[i]->loc ); 
     1304                                        } 
     1305                                        else 
     1306                                        { 
     1307                                                logit( "e", "ewhtmlemail: Unable to create gif image " 
     1308                                                                "for %s.%s.%s.%s\n", 
     1309                                                                sites[i]->name, sites[i]->comp, 
     1310                                                                sites[i]->net, sites[i]->loc ); 
     1311                                                continue; 
     1312                                        } 
     1313 
     1314             
     1315                                        /* Plot Pick 
     1316                                         ***********/ 
     1317                                        pick2gif( gif, arrivalTimes[i], phases[i],  
     1318                                                        starttime, endtime, PICKCOLOR ); 
     1319                  
     1320                  
     1321                                        /* Save gif file 
     1322                                         ***************/ 
     1323                                        sprintf( giffilename, "%s_%ld_%s.%s.%s.%s.gif",  
     1324                                        HTMLFile, arc->sum.qid, 
     1325                                                        sites[i]->name, sites[i]->comp, 
     1326                                                        sites[i]->net, sites[i]->loc ); 
     1327                                        if( ( giffile = fopen( giffilename, "w" ) ) != NULL ) 
     1328                                        { 
     1329                                                if( Debug ) logit( "o", "Saving gif file: %s\n", giffilename ); 
     1330                                                                gdImageGif( gif, giffile ); 
     1331                                                                fclose( giffile ); 
     1332                                        } 
     1333                                        else 
     1334                                        { 
     1335                                                logit( "e", "ewhtmlemail: Unable to save gif file: %s\n",  
     1336                                                                giffilename ); 
     1337                                                gdImageDestroy(gif); 
     1338                                                continue; 
     1339                                        } 
     1340                  
     1341                                        // free gif from memory 
     1342                                        gdImageDestroy(gif); 
     1343                                 
     1344                     
     1345                                        /* Create request for gif file 
     1346                                         *****************************/ 
     1347                                        char *basefilename = (char*)basename( giffilename ); 
     1348                                        snprintf( chartreq, MAX_GET_CHAR,  
     1349                                                        "<img class=\"MapClass\" alt=\"\" src=\"%s\">",  
     1350                                                        basefilename ); 
     1351                                } 
     1352                                else 
     1353                                { 
     1354                         
     1355                                        /* Produce Google trace 
     1356                                         **********************/ 
     1357 
     1358 
     1359                                        /* Resample trace 
     1360                                         ****************/ 
     1361                                        if( Debug ) logit( "o", "Resampling samples for google chart\n" ); 
     1362                                        if( !trbufresample( gsamples, MAX_GET_SAMP, buffer, bsamplecount,  
     1363                                                        starttime, endtime, 30 ) ) // The value 30 comes from google encoding 
     1364                                        { 
     1365                                                logit( "e", "ewhtmlemail: Error resampling samples from " 
     1366                                                                "%s.%s.%s.%s\n", 
     1367                                                                sites[i]->name, sites[i]->comp, 
     1368                                                                sites[i]->net, sites[i]->loc ); 
     1369                                                continue; 
     1370                                        } 
     1371              
     1372                                        /* Produce google charts request 
     1373                                         *******************************/ 
     1374                                        if( Debug ) logit( "o", "Creating google chart request\n" ); 
     1375                                        if( !makeGoogleChart( chartreq, gsamples, MAX_GET_SAMP, phases[i], 
     1376                                                        (int)((arrivalTimes[i]-starttime)/ 
     1377                                                        (endtime-starttime)*100+0.5), 
     1378                                                        TraceWidth, TraceHeight ) ) 
     1379                                        { 
     1380                                                logit( "e", "ewhtmlemail: Error generating google chart for " 
     1381                                                                "%s.%s.%s.%s\n", 
     1382                                                                sites[i]->name, sites[i]->comp, 
     1383                                                                sites[i]->net, sites[i]->loc ); 
     1384                                                continue; 
     1385                                        } 
     1386                                        if( Debug ) logit( "o", "Produced google chart trace for %s.%s.%s.%s\n", 
     1387                                                        sites[i]->name, sites[i]->comp, 
     1388                                                        sites[i]->net, sites[i]->loc ); 
     1389                                } // End of decision to make GIF or google chart traces 
     1390          
     1391          
     1392                                /* Add to request to html file 
     1393                                 *****************************/ 
     1394                                ot = ( time_t ) arrivalTimes[i]; 
     1395                                timeinfo = timefunc ( &ot ); 
     1396                                strftime( timestr,80,"%Y.%m.%d %H:%M:%S", timeinfo ); 
     1397                                fprintf(htmlfile, "<tr class=\"WaveTableTextRowClass\"><td>%c : " 
     1398                                                "%5s.%3s.%2s.%2s %s %s - Dur. %d s - " 
     1399                                                "PickQuality %d - Distance %5.1f km", 
     1400                                                phases[i], sites[i]->name, sites[i]->comp, 
     1401                                                sites[i]->net, sites[i]->loc, timestr, 
     1402                                                time_type, coda_lengths[i], weights[i], distances[i]); 
     1403                         
     1404                                // Include coda magnitudes, if available 
     1405                                if( coda_mags[i] != 0.0 ) 
     1406                                { 
     1407                                        fprintf( htmlfile, " <b>Md=%3.1f</b>", coda_mags[i] ); 
     1408                                } 
     1409                         
     1410                                // Create the table row with the chart request 
     1411                                fprintf( htmlfile, "</td></tr>\n" 
     1412                                                "<tr class=\"WaveTableTraceRowClass\"><td>%s</td></tr>\n",  
     1413                                                chartreq); 
     1414          
     1415                        } // End of trace for cycle 
     1416       
     1417                        // Free buffer 
     1418                        free( buffer ); 
     1419                 
     1420                        // Finish trace table 
     1421                        fprintf(htmlfile, "</table>\n"); 
     1422                 
     1423                } // End of Traces section 
     1424 
     1425 
     1426 
     1427                /* print out all the ML TYPE_MAGNITUDE info  
     1428                 ******************************************/ 
     1429                if ( UseML && mag != NULL ) 
     1430                { 
     1431                        fprintf( htmlfile, "<hr><a name=\"ML\"></a><table id=\"DataTable\">\n" ); 
     1432                        fprintf( htmlfile, "<tr><td colspan=3><a name=\"ML\">Local Magnitude:</a> %4.1f " 
     1433                                        "&plusmn;%3.1f %s nchans=%d nstas=%d</td><tr>\n",  
     1434                                        mag->mag, mag->error, MAG_MSG_TYPE_STRING, 
     1435                                        mag->nchannels, mag->nstations ); 
     1436                        fprintf( htmlfile, "<tr><th>S.C.N.L</th><th>Magnitude</th>" 
     1437                                        "<th>Distance(km)</th></tr>\n" ); 
     1438                        for( i = 0; i < mag->nchannels; i++ )  
     1439                        { 
     1440                                MAG_CHAN_INFO *pMagchan; 
     1441                                pMagchan = (MAG_CHAN_INFO *) mag->pMagAux + i; 
     1442                                if( i % 2 ) 
     1443                                { 
     1444                                        fprintf( htmlfile, "<tr>" ); 
     1445                                }  
     1446                                else  
     1447                                { 
     1448                                        fprintf( htmlfile, "<tr class=\"alt\">" ); 
     1449                                } 
     1450                                fprintf( htmlfile, "<td>%s.%s.%s.%s</td>",  
     1451                                                pMagchan->sta, pMagchan->comp,  
     1452                                                pMagchan->net, pMagchan->loc); 
     1453                                fprintf( htmlfile, "<td align=\"center\">%3.1f</td>", pMagchan->mag ); 
     1454                                fprintf( htmlfile, "<td align=\"center\">%5.1f</td>", pMagchan->dist ); 
     1455                                fprintf( htmlfile, "</tr>\n" ); 
     1456                        } 
     1457                        fprintf(htmlfile, "</table>\n"); 
     1458                } // End of ML 'for' cycle 
    10691459       
    10701460       
    1071       /* Create table with reference information 
    1072        *****************************************/ 
    1073       ot = (time_t)(arc->sum.ot - GSEC1970); 
    1074       timeinfo = timefunc ( &ot); 
    1075       strftime (timestr,80,"%Y.%m.%d %H:%M:%S",timeinfo); 
    1076       fprintf(htmlfile, "<table id=\"DataTable\">\n"); 
    1077       fprintf(htmlfile, "<tr><th>EW Event ID: %ld<th><tr>\n", arc->sum.qid ); 
    1078       fprintf(htmlfile, "<tr class=\"alt\"><td>Origin time</td><td>%s %s</td><tr>\n",timestr, time_type); 
    1079       fprintf(htmlfile, "<tr><td>Latitude:</td><td>%7.4f</td><tr>\n", arc->sum.lat); 
    1080       fprintf(htmlfile, "<tr class=\"alt\"><td>Longitude:</td><td>%8.4f</td><tr>\n", arc->sum.lon); 
    1081       fprintf(htmlfile, "<tr><td>Depth:</td><td>%4.1f km</td><tr>\n", arc->sum.z); 
    1082       fprintf(htmlfile, "<tr class=\"alt\"><td>Coda Magnitude:</td><td>%4.1f %s nobs=%d</td><tr>\n",  
    1083               arc->sum.Mpref, MAG_TYPE_STRING, (int) arc->sum.mdwt); 
    1084       if (UseML && mag != NULL) { 
    1085            fprintf(htmlfile, "<tr class=\"alt\"><td><a href=\"#ML\">Local Magnitude:</a></td><td>%4.1f &plusmn;%3.1f %s nobs=%d</td><tr>\n",  
    1086                    mag->mag, mag->error, MAG_MSG_TYPE_STRING, mag->nchannels); 
    1087       } 
    1088       if (ShowDetail) { 
    1089           char Quality; 
    1090     
    1091           fprintf(htmlfile, "<tr><td>RMS Error:</td><td>%5.2f s</td><tr>\n", arc->sum.rms); 
    1092           fprintf(htmlfile, "<tr class=\"alt\"><td>Horizontal Error:</td><td>%5.2f km</td><tr>\n", arc->sum.erh); 
    1093           fprintf(htmlfile, "<tr><td>Depth Error:</td><td>%5.2f km</td><tr>\n", arc->sum.erz); 
    1094           fprintf(htmlfile, "<tr class=\"alt\"><td>Azimuthal Gap:</td><td>%d Degrees</td><tr>\n", arc->sum.gap); 
    1095           fprintf(htmlfile, "<tr><td>Total Phases:</td><td>%d</td><tr>\n", arc->sum.nphtot); 
    1096           fprintf(htmlfile, "<tr class=\"alt\"><td>Total Phases Used:</td><td>%d</td><tr>\n", arc->sum.nph); 
    1097           fprintf(htmlfile, "<tr><td>Num S Phases Used:</td><td>%d</td><tr>\n", arc->sum.nphS); 
    1098           Quality = ComputeAverageQuality(arc->sum.rms, arc->sum.erh, arc->sum.erz, arc->sum.z, (float) (1.0*arc->sum.dmin), arc->sum.nph, arc->sum.gap); 
    1099           fprintf(htmlfile, "<tr class=\"alt\"><td>Quality:</td><td>%c</td><tr>\n", Quality); 
    1100       } 
    1101       fprintf(htmlfile, "</table><br><br>\n"); 
    1102           
    1103           
    1104       /* Introduce google map with the stations and hypocenter 
    1105        *******************************************************/ 
    1106       if (Debug) logit("ot", "Computing Google map\n"); 
    1107       GoogleMapRequest(req, &nreq, sites, nsites, arc->sum.lat, arc->sum.lon); 
    1108       fprintf(htmlfile, "%s\n<br><br>", req); 
    1109        
    1110     
    1111       /* Introduce google chars with station traces 
    1112        ********************************************/ 
    1113       if (Debug) logit("ot", "Computing Google charts\n"); 
    1114       st = (time_t) starttime; 
    1115       timeinfo = timefunc ( &st); 
    1116       strftime (timestr,80,"%Y.%m.%d %H:%M:%S",timeinfo); 
    1117       fprintf(htmlfile, "<table id=\"WaveTable\">\n");  
    1118       fprintf(htmlfile, "<tr><th>Waveforms: (StartTime: %s Duration: %d seconds)</th></tr>\n", timestr, dur);  
    1119       for (i=0; i<nsites; i++) 
    1120       { 
    1121          /* Download trace for the site 
    1122           *****************************/ 
    1123          if (getWSData(sites[i],starttime, endtime, trace, nsamples)!=0) 
    1124          { 
    1125             logit("t", "ewhtmlemail: Unable to retrieve data from waveserver\n"); 
    1126             continue; 
    1127          } 
    1128        
    1129          /* Create trace image request 
    1130           ****************************/ 
    1131          nreq = 0; //Actual number of characters of the request 
    1132          GoogleChartRequest(req, &nreq, trace, nsamples, i, 
    1133             phases[i], 
    1134             (int)((arrivalTimes[i]-starttime)/(endtime-starttime)*100+0.5)); 
    1135          if (Debug) logit("o", "Produced trace for %s.%s.%s.%s with %d characters\n", 
    1136             sites[i]->name, sites[i]->comp, 
    1137             sites[i]->net, sites[i]->loc, 
    1138             nreq); 
    1139        
    1140          /* Add to email file 
    1141           *******************/ 
    1142          ot = (time_t)arrivalTimes[i]; 
    1143          timeinfo = timefunc ( &ot); 
    1144          strftime (timestr,80,"%Y.%m.%d %H:%M:%S",timeinfo); 
    1145          fprintf(htmlfile, "<tr class=\"WaveTableTextRowClass\"><td>%c : %5s.%3s.%2s.%2s %s %s - Dur. %d s - PickQuality %d - Distance %5.1f km", 
    1146                phases[i], sites[i]->name, sites[i]->comp, sites[i]->net, sites[i]->loc, timestr, 
    1147                time_type, coda_lengths[i], weights[i], distances[i]); 
    1148          if (coda_mags[i] != 0.0) { 
    1149             fprintf(htmlfile, " <b>Md=%3.1f</b>", coda_mags[i]); 
    1150          } 
    1151          fprintf(htmlfile, "</td></tr>\n<tr class=\"WaveTableTraceRowClass\"><td>%s</td></tr>\n", req);  
    1152       } 
    1153       fprintf(htmlfile, "</table>\n"); 
    1154  
    1155        
    1156       /* print out all the ML TYPE_MAGNITUDE info */ 
    1157       if (UseML && mag != NULL) { 
    1158            fprintf(htmlfile, "<hr><a name=\"ML\"></a><table id=\"DataTable\">\n"); 
    1159            fprintf(htmlfile, "<tr><td colspan=3><a name=\"ML\">Local Magnitude:</a> %4.1f &plusmn;%3.1f %s nchans=%d nstas=%d</td><tr>\n",  
    1160                    mag->mag, mag->error, MAG_MSG_TYPE_STRING, mag->nchannels, mag->nstations); 
    1161            fprintf(htmlfile, "<tr><th>S.C.N.L</th><th>Magnitude</th><th>Distance(km)</th></tr>\n"); 
    1162            for (i=0; i< mag->nchannels; i++)  
    1163            { 
    1164                MAG_CHAN_INFO *pMagchan; 
    1165                pMagchan = (MAG_CHAN_INFO *) mag->pMagAux + i; 
    1166                if (i%2) { 
    1167                   fprintf(htmlfile, "<tr>"); 
    1168                } else { 
    1169                   fprintf(htmlfile, "<tr class=\"alt\">"); 
    1170                } 
    1171                fprintf(htmlfile, "<td>%s.%s.%s.%s</td>", pMagchan->sta, pMagchan->comp, pMagchan->net, pMagchan->loc); 
    1172                fprintf(htmlfile, "<td align=\"center\">%3.1f</td>", pMagchan->mag); 
    1173                fprintf(htmlfile, "<td align=\"center\">%5.1f</td>", pMagchan->dist); 
    1174                fprintf(htmlfile, "</tr>\n"); 
    1175            } 
    1176            fprintf(htmlfile, "</table>\n"); 
    1177       } 
    1178        
    1179       /* Finish file 
    1180        *************/ 
    1181        if (Debug) logit("ot", "Closing file\n"); 
    1182       fprintf(htmlfile,"</body>\n</html>\n"); 
    1183       fclose(htmlfile); 
     1461                /* Finish html file 
     1462                 ******************/ 
     1463                if( Debug ) logit( "ot", "Closing file\n" ); 
     1464                fprintf(htmlfile,"</body>\n</html>\n"); 
     1465                fclose(htmlfile); 
    11841466       
    11851467       
    1186       /* Execute command 
    1187        *****************/ 
    1188       if (strlen(EmailProgram)>0 && nemailrecipients>0) 
    1189       { 
    1190          logit("ot", "ewhtmlemail: Sending email alert.\n"); 
    1191          for (i=0; i<nemailrecipients; i++) 
    1192          { 
    1193              
    1194             if (UseBlat) { 
    1195               if (kml_filename[0] == 0) { 
    1196                   sprintf(system_command,"%s %s -html -to %s -subject \"%s - EW Event ID: %ld\" %s", 
    1197                    EmailProgram, fullFilename, emailrecipients[i].address, SubjectPrefix, arc->sum.qid, BlatOptions); 
    1198               } else { 
    1199                   /* the latest version of blat supports -attacht option for text file attachment, send the KML file */ 
    1200                   sprintf(system_command,"%s %s -html -to %s -subject \"%s - EW Event ID: %ld\" -attacht %s %s", 
    1201                         EmailProgram, fullFilename, emailrecipients[i].address, SubjectPrefix,  
    1202                         arc->sum.qid, kml_filename, BlatOptions); 
    1203               } 
    1204             } else { 
    1205               /* this syntax below is for UNIX mail, which on most systems does not handle HTML content type, may use that in future...*/ 
    1206               /*        sprintf(system_command,"cat %s | %s -s '%s - EW Event ID: %ld' %s", 
    1207                fullFilename, EmailProgram, SubjectPrefix, arc->sum.qid, emailrecipients[i].address); 
    1208                */ 
    1209  
    1210                /* sendmail -t handles in line To: and other header info */ 
    1211                sprintf(hdrFilename, "%s_header.tmp", HTMLFile); 
    1212                header_file = fopen(hdrFilename, "w"); 
    1213                fprintf(header_file, "To: %s\n", emailrecipients[i].address); 
    1214                fprintf(header_file, "Subject: %s - EW Event ID: %ld\n", SubjectPrefix, arc->sum.qid); 
    1215                fprintf(header_file, "Content-Type: text/html\n\n");  
    1216                fclose(header_file); 
    1217                sprintf(system_command,"cat %s %s | %s -t ", hdrFilename, fullFilename, EmailProgram); 
    1218  
    1219             } 
    1220             system(system_command); 
    1221          } 
    1222       } 
    1223    } 
    1224    else 
    1225    { 
    1226       logit("et", "ewhtmlemail: Unable to write html file\n"); 
    1227    } 
    1228    /* Release memory 
    1229     ****************/ 
    1230    free(trace); 
    1231    return FALSE; 
     1468                /* Send email 
     1469                 *****************/ 
     1470                if( strlen( EmailProgram ) > 0 && nemailrecipients > 0 ) 
     1471                { 
     1472                        logit( "ot", "ewhtmlemail: Sending email alert.\n" ); 
     1473                        for( i=0; i<nemailrecipients; i++ )// One email for each recipient 
     1474                        { 
     1475                 
     1476                                if( UseBlat )           // Use blat for sending email 
     1477                                { 
     1478                                        if( kml_filename[0] == 0 ) 
     1479                                        { 
     1480                                                sprintf(system_command,"%s %s -html -to %s -subject \"%s " 
     1481                                                                "- EW Event ID: %ld\" %s", 
     1482                                                                EmailProgram, fullFilename, emailrecipients[i].address, 
     1483                                                                SubjectPrefix, arc->sum.qid, BlatOptions); 
     1484                                        } 
     1485                                        else 
     1486                                        { 
     1487                                                /* the latest version of blat supports -attacht option for text file attachment, send the KML file */ 
     1488                                                sprintf(system_command,"%s %s -html -to %s -subject \"%s " 
     1489                                                                "- EW Event ID: %ld\" -attacht %s %s", 
     1490                                                                EmailProgram, fullFilename, emailrecipients[i].address,  
     1491                                                                SubjectPrefix, arc->sum.qid, kml_filename, BlatOptions); 
     1492                                        } 
     1493                                } 
     1494                                else                            // Use sendmail 
     1495                                { 
     1496                                        /* this syntax below is for UNIX mail, which on most systems does  
     1497                                         * not handle HTML content type, may use that in future... 
     1498                                         ****************************************************************/ 
     1499                                        /*sprintf(system_command,"cat %s | %s -s '%s - EW Event ID: %ld' %s", 
     1500                                                        fullFilename, EmailProgram, SubjectPrefix, 
     1501                                                        arc->sum.qid, emailrecipients[i].address); 
     1502                                        */ 
     1503 
     1504                                        /* sendmail -t handles in line To: and other header info */ 
     1505                                 
     1506                                        /* Create email header file 
     1507                                         **************************/ 
     1508                                        sprintf( hdrFilename, "%s_header.tmp", HTMLFile ); 
     1509                                        header_file = fopen( hdrFilename, "w" ); 
     1510                                        fprintf( header_file, "To: %s\n", emailrecipients[i].address ); 
     1511                                        fprintf( header_file, "Subject: %s - EW Event ID: %ld\n",  
     1512                                                        SubjectPrefix, arc->sum.qid ); 
     1513                                        fprintf( header_file, "Content-Type: text/html\n\n" );  
     1514                                        fclose( header_file ); 
     1515                                         
     1516                                        /* System command for sendmail */ 
     1517                                        sprintf(system_command,"cat %s %s | %s -t ",  
     1518                                                        hdrFilename, fullFilename, EmailProgram); 
     1519                                } 
     1520                         
     1521                                /* Execute system command to send email 
     1522                                 **************************************/ 
     1523                                system(system_command); 
     1524                        } 
     1525                } 
     1526        } 
     1527        else 
     1528        { 
     1529                logit("et", "ewhtmlemail: Unable to write html file\n"); 
     1530                return FALSE; 
     1531        } 
     1532        return TRUE; 
    12321533} 
     1534 
     1535 
     1536 
     1537 
     1538 
     1539 
     1540 
     1541 
     1542 
     1543 
     1544 
     1545 
    12331546 
    12341547/******************************************************************************* 
     
    12361549 *                   and a hypocenter                                          * 
    12371550 ******************************************************************************/ 
    1238 void GoogleMapRequest(char *request, int *nchars, SITE **sites, int nsites, 
     1551void GoogleMapRequest(char *request, SITE **sites, int nsites, 
    12391552   double hypLat, double hypLon) 
    12401553{ 
    12411554   int i; 
    1242    char markerstr[MAX_STRING_SIZE]; 
     1555   char temp[MAX_GET_CHAR]; 
    12431556 
    12441557    
    12451558   /* Base of the google static map 
    12461559    *******************************/ 
    1247    *nchars = sprintf(request, "<img class=\"MapClass\" alt=\"\" src=\"http://maps.google.com/maps/api/staticmap?" 
    1248       "size=600x400&format=png8&maptype=hybrid&sensor=false");    
    1249  
    1250    /* Add icon for hypocenter 
    1251     *************************/ 
     1560   snprintf(request, MAX_GET_CHAR, "<img class=\"MapClass\" alt=\"\" " 
     1561         "src=\"http://maps.google.com/maps/api/staticmap?" 
     1562         "size=600x400&format=png8&maptype=hybrid&sensor=false");    
     1563    
     1564   /* Icon for hypocenter  
     1565    *********************/ 
    12521566   if (hypLat!=0.0 || hypLon!=0.0) 
    1253    {                         //         http://      maps.google.com/   mapfiles/   kml/   paddle/   ylw-stars.png 
    1254       sprintf(markerstr, "&markers=icon:http:%%2F%%2Fmaps.google.com%%2Fmapfiles%%2Fkml%%2Fpaddle%%2Fylw-stars.png|shadow:true|%f,%f", hypLat, hypLon); 
    1255       strcat(request, markerstr); 
    1256       *nchars += strlen(markerstr); 
     1567   { 
     1568      snprintf( temp, MAX_GET_CHAR, "%s&markers=icon:http:%%2F%%2Fmaps.google.com%%2" 
     1569            "Fmapfiles%%2Fkml%%2Fpaddle%%2Fylw-stars.png|shadow:true|%f,%f",  
     1570            request, hypLat, hypLon); 
     1571      snprintf( request, MAX_GET_CHAR, "%s", temp ); 
    12571572   } 
    12581573 
    12591574   /* Add icons for stations 
    12601575    ************************/ 
    1261    sprintf(markerstr,"&markers=icon:http:%%2F%%2Fmaps.google.com%%2Fmapfiles%%2Fkml%%2Fshapes%%2Fplacemark_circle.png|shadow:false"); 
    1262    strcat(request, markerstr); 
    1263    *nchars += strlen(markerstr); 
    1264    for (i=0; i<nsites; i++) 
     1576   snprintf( temp, MAX_GET_CHAR, "%s&markers=icon:http:%%2F%%2Fmaps.google.com%%2Fmapfiles" 
     1577         "%%2Fkml%%2Fshapes%%2Fplacemark_circle.png|shadow:false", request ); 
     1578   snprintf( request, MAX_GET_CHAR, "%s", temp ); 
     1579   for( i = 0; i < nsites; i++ ) 
    12651580   { 
    1266       sprintf(markerstr, "|%f,%f", sites[i]->lat, sites[i]->lon); 
    1267       if ((*nchars + strlen(markerstr))>=MAX_GET_CHAR) 
    1268          break; 
    1269       *nchars += strlen(markerstr); 
    1270       strcat(request, markerstr); 
     1581      snprintf( temp, MAX_GET_CHAR, "%s|%f,%f", request, sites[i]->lat, sites[i]->lon ); 
     1582      snprintf( request, MAX_GET_CHAR, "%s", temp ); 
    12711583   } 
    12721584    
    1273    strcat(request, "\"/>"); 
    1274    printf("\n"); 
     1585   /* End of the request 
     1586    ********************/ 
     1587   snprintf( temp, MAX_GET_CHAR, "%s\"/>", request ); 
     1588   snprintf( request, MAX_GET_CHAR, "%s", temp ); 
    12751589    
    12761590} 
    12771591 
    12781592 
     1593 
     1594 
     1595 
     1596 
     1597 
     1598 
     1599 
     1600 
     1601 
     1602 
     1603 
     1604 
     1605 
     1606 
    12791607/******************************************************************************* 
    1280  * makeGoogleChartRequest: Produce a google chary request for a given station  * 
     1608 * makeGoogleChartRequest: Produce a google chart request for a given station  * 
    12811609 ******************************************************************************/ 
    12821610 /*  
    12831611 * Input Parameters 
    1284  * request:         String to save the request in  
    1285  * nchars:          Corresponding number of charanters 
     1612 * chartreq:        String to save the request in  
    12861613 * samples:         Array with the samples 
    1287  * nsamples:        Number of samples 
    1288  * counter:         A counter to return the actual number of characters 
     1614 * samplecount:     Number of samples 
    12891615 * phaseName:       A character to indicate the name of the phase (P or S) 
    12901616 * phasePos:        The relative position of the phase label 0%-100% 
     1617 * tracewidth:      Width of the google trace 
     1618 * traceheight:     Height of the google trace 
    12911619 */ 
    1292 void GoogleChartRequest(char *request, int *nchars,  
    1293    double *samples, int nsamples, int counter, 
    1294    char phaseName, int phasePos)  
     1620int makeGoogleChart( char* chartreq, int *samples, int samplecount,  
     1621                char phasename, int phasepos, int tracewidth, int traceheight ) 
    12951622{ 
    1296    int i; 
    1297    double maxSamp = 0; 
    1298     
    1299     
    1300    /* Compute maximum of the samples 
    1301     ********************************/ 
    1302    for (i=0; i<nsamples; i++) 
    1303       if (samples[i]>maxSamp) 
    1304       { 
    1305          maxSamp = samples[i]; 
    1306       } 
    1307       else if (-samples[i]>maxSamp) 
    1308       { 
    1309          maxSamp = -samples[i]; 
    1310       } 
    1311           
    1312    /* Introduce request header 
    1313     **************************/ 
    1314    *nchars = sprintf(request, "<img class=\"TraceClass\" alt=\"\" src=\"http://chart.apis.google.com/chart?chs=%dx61&cht=ls&chxt=x&chxl=0:|%c&chxp=0,%d&chxtc=0,-600&chco=000060&chma=0,0,0,0&chls=2&chd=s:", 
    1315          600, phaseName, phasePos);//nsamples); 
    1316     
    1317    for (i=0; i<nsamples; i++) 
    1318    { 
    1319       request[(*nchars)++] = simpleEncode((int)(((samples[i]/maxSamp)/2 + 0.5) * 60)); 
    1320       //request[(*nchars)++] = ','; 
    1321    } 
    1322    request[(*nchars)++] = '\"'; 
    1323    request[(*nchars)++] = '/'; 
    1324    request[(*nchars)++] = '>'; 
    1325    request[(*nchars)++] = '\0'; //Terminate string; 
    1326     
    1327    return; 
     1623        int i; 
     1624        double avg; 
     1625        char reqHeader[MAX_GET_CHAR]; 
     1626        char reqSamples[MAX_GET_CHAR]; 
     1627         
     1628        // Average value of the samples 
     1629        avg = 0; 
     1630        for( i = 0; i < samplecount; i++ ) 
     1631                avg += samples[i]; 
     1632        avg /= ( double ) samplecount; 
     1633         
     1634         
     1635        /* Create request header 
     1636         ***********************/ 
     1637        snprintf(reqHeader, MAX_GET_CHAR, "<img class=\"TraceClass\" alt=\"\" " 
     1638                        "src=\"http://chart.apis.google.com/chart?" 
     1639                        "chs=%dx%d&" 
     1640                        "cht=ls&" 
     1641                        "chxt=x&" 
     1642                        "chxl=0:|%c&" 
     1643                        "chxp=0,%d&" 
     1644                        "chxtc=0,-600&" 
     1645                        "chco=000060&" 
     1646                        "chma=0,0,0,0&" 
     1647                        "chls=2&" 
     1648                        "chd=s:", 
     1649                        tracewidth, traceheight, phasename, phasepos); 
     1650         
     1651        /* Add samples to request 
     1652         ************************/ 
     1653    for( i = 0; i < samplecount  && i < ( MAX_GET_CHAR - 1 ); i++ ) 
     1654        reqSamples[i] = simpleEncode( ( int )( ( double ) samples[i] - avg + 30.5 ) ); 
     1655    reqSamples[samplecount] = '\0'; 
     1656     
     1657    /* Combine header and samples 
     1658     ****************************/ 
     1659    snprintf( chartreq, MAX_GET_CHAR, "%s%s\"/>", reqHeader, reqSamples ); 
     1660     
     1661    return 1; 
    13281662} 
     1663 
     1664 
     1665 
     1666 
     1667 
     1668 
     1669 
     1670 
     1671 
     1672 
     1673 
    13291674 
    13301675 
     
    13461691   return base[i]; 
    13471692} 
     1693 
     1694 
     1695 
     1696 
     1697 
     1698 
     1699 
     1700 
     1701 
    13481702 
    13491703 
     
    13751729 
    13761730 
    1377 /******************************************************************************* 
    1378  * getWSData: Retrieve data from the waveserver and store it in the stations   * 
    1379  *            structure. The trace data is high-pass filtered and sub-sampled  * 
    1380  *******************************************************************************/ 
    1381 int getWSData(SITE *site,  
    1382    double starttime, double endtime,  
    1383    double *trace, int nsamples) 
     1731 
     1732 
     1733 
     1734 
     1735 
     1736 
     1737 
     1738 
     1739 
     1740/**************************************************************************************** 
     1741 * getWStrbf: Retrieve a set of samples from the waveserver and store the raw tracebuf2 * 
     1742 *            in a buffer                                                               * 
     1743 ****************************************************************************************/ 
     1744int getWStrbf( char *buffer, int *buflen, SITE *site, 
     1745                double starttime, double endtime ) 
    13841746{ 
    1385    char *buffer;                   /* Buffer to store data from the waveserver */ 
    1386    WS_MENU_QUEUE_REC menu_queue; 
    1387    TRACE_REQ trace_req; 
    1388    int wsResponse; 
    1389    TRACE2_HEADER *trace_header; 
    1390    double lastEndtime = 0; 
    1391    char* sampP; 
    1392    int bps; 
    1393    int i; 
    1394    int samples[(MAX_TRACEBUF_SIZ-64)/2]; /* Samples for a single tracebuf2 */ 
    1395    double sampleAvg = 0;           /* To remove average */ 
    1396    int samplePos = 0;              /* Current sample on trace */ 
    1397    double deltaT = (endtime - starttime)/(double)nsamples; 
    1398    double curSampleTime = starttime; 
    1399    double curTime; 
    1400    int completedAcquisition = 0; 
    1401    char WSErrorMsg[80]; /* To write ws error messages */ 
    1402    int atLeastOne = 0; 
    1403    double processedSample = 0; 
    1404    double sampleMaximum = 0; 
    1405    int getMaximum = 0; 
     1747        WS_MENU_QUEUE_REC       menu_queue; 
     1748        TRACE_REQ                       trace_req; 
     1749        int                             wsResponse; 
     1750        int                                     atLeastOne; 
     1751        int                                     i; 
     1752        char                            WSErrorMsg[80]; 
     1753         
     1754        /* Initialize menu queue 
     1755         ***********************/ 
     1756        menu_queue.head = NULL; 
     1757        menu_queue.tail = NULL; 
     1758         
     1759         
     1760        /* Make menu request 
     1761    *******************/ 
     1762        for( i = 0; i < nwaveservers; i++ ) 
     1763        { 
     1764                wsResponse = wsAppendMenu( 
     1765                                waveservers[i].wsIP, waveservers[i].port,  
     1766                                &menu_queue, wstimeout ); 
     1767                if( wsResponse != WS_ERR_NONE ) 
     1768                { 
     1769                        logit( "et", "ewhtmlemail: Cannot contact waveserver %s:%s - ", 
     1770                                        waveservers[i].wsIP, waveservers[i].port, wsResponse ); 
     1771                        logit( "et", "%s\n", 
     1772                                        getWSErrorStr(wsResponse, WSErrorMsg ) ); 
     1773                        continue; 
     1774                } 
     1775                else 
     1776                { 
     1777                        atLeastOne++; 
     1778                } 
     1779        } 
     1780        if( atLeastOne == 0 ) 
     1781        { 
     1782                logit( "et", "ewhtmlemail: Unable to contact any waveserver.\n"); 
     1783                return -1; 
     1784        } 
     1785         
     1786         
     1787        /* Make request structure 
     1788        ************************/ 
     1789        strcpy( trace_req.sta, site->name ); 
     1790        strcpy( trace_req.chan, site->comp ); 
     1791        strcpy( trace_req.net, site->net ); 
     1792        strcpy( trace_req.loc, site->loc ); 
     1793        trace_req.reqStarttime = starttime; 
     1794        trace_req.reqEndtime = endtime; 
     1795        trace_req.partial = 1; 
     1796        trace_req.pBuf = buffer; 
     1797        trace_req.bufLen = *buflen; 
     1798        trace_req.timeout = wstimeout; 
     1799        trace_req.fill = 0; 
    14061800    
    14071801    
    1408    /* Allocate memory for buffer 
    1409     ****************************/ 
    1410    buffer = (char*) malloc(MAX_SAMPLES * 4); 
    1411    if (buffer==NULL) 
    1412    { 
    1413       logit( "et", "ewhtmlemail: Cannot allocate buffer for trace\n" ); 
    1414       return -1; 
    1415    } 
    1416     
    1417     
    1418    /* Initialize trace 
    1419     ******************/ 
    1420    for (i=0; i<nsamples; i++) 
    1421    { 
    1422       trace[i] = 0; 
    1423    } 
    1424     
    1425     
    1426    /* Initialize menu queue 
    1427     ***********************/ 
    1428    menu_queue.head = NULL; 
    1429    menu_queue.tail = NULL; 
    1430     
    1431     
    1432    /* Make menu request 
    1433     *******************/ 
    1434    for (i=0; i<nwaveservers; i++) 
    1435    { 
    1436       wsResponse = wsAppendMenu( 
    1437          waveservers[i].wsIP, waveservers[i].port,  
    1438          &menu_queue, wstimeout); 
    1439       if (wsResponse!=WS_ERR_NONE) 
    1440       { 
    1441          logit( "et", "ewhtmlemail: Cannot contact waveserver %s:%s - ", 
    1442             waveservers[i].wsIP, waveservers[i].port, wsResponse); 
    1443          logit( "et", "%s\n", 
    1444             getWSErrorStr(wsResponse, WSErrorMsg)); 
    1445          continue; 
    1446       } 
    1447       else 
    1448       { 
    1449          atLeastOne++; 
    1450       } 
    1451    } 
    1452    if (atLeastOne == 0) 
    1453    { 
    1454       logit( "et", "ewhtmlemail: Unable to contact any waveserver.\n"); 
    1455       return -1; 
    1456    } 
    1457     
    1458     
    1459    /* Make request structure 
    1460     ************************/ 
    1461    strcpy(trace_req.sta, site->name); 
    1462    strcpy(trace_req.chan, site->comp); 
    1463    strcpy(trace_req.net, site->net); 
    1464    strcpy(trace_req.loc, site->loc); 
    1465    trace_req.reqStarttime = starttime; 
    1466    trace_req.reqEndtime = endtime; 
    1467    trace_req.partial = 1; 
    1468    trace_req.pBuf = buffer; 
    1469    trace_req.bufLen = MAX_SAMPLES*4; 
    1470    trace_req.timeout = wstimeout; 
    1471    trace_req.fill = 0; 
    1472     
    1473     
    1474    /* Pull data from ws 
    1475     *******************/ 
    1476    wsResponse = wsGetTraceBinL( &trace_req, &menu_queue, wstimeout ); 
    1477    if (wsResponse!=WS_ERR_NONE) 
    1478    { 
    1479       logit( "et", "ewhtmlemail: Error loading data from waveserver - %s\n", 
    1480          getWSErrorStr(wsResponse, WSErrorMsg)); 
    1481       return -1; 
    1482    } 
    1483     
    1484     
    1485    /* Prepare for tracebuf2 analyzing cycle 
    1486     ***************************************/ 
    1487    trace_header = (TRACE2_HEADER*)buffer; 
    1488     
    1489     
    1490    /* Tracebuf analyzing cycle 
    1491     **************************/ 
    1492    while (trace_header < (TRACE2_HEADER*)(buffer + trace_req.actLen) && 
    1493       completedAcquisition == 0) 
    1494    { 
    1495       /* If necessary, swap bytes in tracebuf message 
    1496        ***********************************************/ 
    1497       if ( WaveMsg2MakeLocal( trace_header ) < 0 ) 
    1498       { 
    1499          logit( "et", "ewhtmlemail: WaveMsg2MakeLocal error.\n" ); 
    1500          continue; 
    1501       } 
    1502       
    1503      /* Check for gaps 
    1504       ****************/ 
    1505      if ((trace_header->starttime - lastEndtime) > (1/trace_header->samprate)) 
    1506      { 
    1507         /* Detected GAP... Do nothing 
    1508          ****************************/ 
    1509      } 
    1510      lastEndtime = trace_header->endtime; 
    1511        
    1512        
    1513      /* Convert samples to int 
    1514       ************************/ 
    1515      sampP = (char*)trace_header + 64; //Position of the first sample 
    1516      sampleAvg = 0; 
    1517      if ( strcmp(trace_header->datatype, "i2")==0 || 
    1518         strcmp(trace_header->datatype, "s2")==0 ) 
    1519      {    
    1520         bps = 2; 
    1521         for (i = 0; i<trace_header->nsamp; i++) 
    1522         { 
    1523            samples[i] = (int)(*((short*)sampP)); 
    1524            sampleAvg += (double)samples[i]; 
    1525            sampP += bps; 
    1526         } 
    1527      } 
    1528      else 
    1529      { 
    1530         bps = 4; 
    1531         for (i = 0; i<trace_header->nsamp; i++) 
    1532         { 
    1533            samples[i] = *((int*)sampP); 
    1534            sampleAvg += (double)samples[i]; 
    1535            sampP += bps; 
    1536         } 
    1537      } 
    1538      sampleAvg /= (double)trace_header->nsamp; 
    1539       
    1540      /* Process samples 
    1541       *****************/ 
    1542      processedSample = 0; 
    1543      sampleMaximum = 0; 
    1544      getMaximum = 0; 
    1545      for (i=0; i<trace_header->nsamp; i++) 
    1546      { 
    1547         processedSample = (double)samples[i] - sampleAvg; 
    1548         if (getMaximum==1) 
    1549         { 
    1550            if (processedSample>sampleMaximum) 
    1551               sampleMaximum = processedSample; 
    1552         } 
    1553         else 
    1554         { 
    1555            if (processedSample<sampleMaximum) 
    1556               sampleMaximum = processedSample; 
    1557         } 
    1558       
    1559         /* Check if this sample shold be stored 
    1560          **************************************/ 
    1561         curTime = trace_header->starttime + (double)i/trace_header->samprate; 
    1562         if (((curTime-curSampleTime) <= 1/(2*trace_header->samprate)) && 
    1563            ((curTime-curSampleTime) > -1/(2*trace_header->samprate))) 
    1564         { 
    1565            /* Store sample in output array and update time 
    1566             **********************************************/ 
    1567            //trace[samplePos++] = (double)samples[i] - sampleAvg; 
    1568            trace[samplePos++] = sampleMaximum; 
    1569            getMaximum = 1-getMaximum; 
    1570            sampleMaximum = 0; 
    1571             
    1572            curSampleTime += deltaT; 
    1573             
    1574             
    1575            /* Check if number of required samples has been reached 
    1576             ******************************************************/ 
    1577            if (samplePos>=nsamples) 
    1578            { 
    1579               completedAcquisition = 1; 
    1580               break; 
    1581            } 
    1582         } 
    1583      } 
    1584       
    1585     
    1586       /* Update trace_header pointer 
    1587        *****************************/ 
    1588       trace_header = (TRACE2_HEADER*)sampP;  
    1589    } 
    1590     
    1591    /* Terminate connection 
    1592     **********************/ 
    1593    wsKillMenu(&menu_queue); 
    1594     
    1595     
    1596    /* Free memory 
    1597     *************/ 
    1598    free(buffer); 
    1599     
    1600    /* Done! 
    1601     *******/ 
    1602    return 0; 
    1603 } 
     1802        /* Pull data from ws 
     1803         *******************/ 
     1804        wsResponse = wsGetTraceBinL( &trace_req, &menu_queue, wstimeout ); 
     1805        if( wsResponse != WS_ERR_NONE ) 
     1806        { 
     1807                logit( "et", "ewhtmlemail: Error loading data from waveserver - %s\n", 
     1808                                getWSErrorStr(wsResponse, WSErrorMsg)); 
     1809                return -1; 
     1810        } 
     1811         
     1812        /* Update output number of bytes 
     1813         *********************************/ 
     1814        *buflen = (int)trace_req.actLen; 
     1815         
     1816         
     1817        /* Terminate connection 
     1818     **********************/ 
     1819    wsKillMenu(&menu_queue); 
     1820     
     1821    return 1; 
     1822}                
     1823 
     1824 
     1825 
     1826 
     1827 
    16041828 
    16051829 
     
    16591883 
    16601884 
    1661  
    1662  
    1663  
    1664  
    1665  
    1666  
    1667  
    1668  
    1669  
    1670  
    1671  
     1885/**************************************************************************************** 
     1886 * trbufresample: Resample a trace buffer to a desired sample rate. Uses squared low    * 
     1887 *            filtering and oversampling                                                * 
     1888 ****************************************************************************************/ 
     1889int trbufresample( int *outarray, int noutsig, char *buffer, int buflen, 
     1890                double starttime, double endtime, int outamp ) 
     1891{ 
     1892        TRACE2_HEADER   *trace_header;          // Pointer to the header of the current trace 
     1893        char                    *trptr;                         // Pointer to the current sample 
     1894        double                  inrate;                         // Initial sampling rate 
     1895        double                  outrate;                        // Output rate 
     1896        int                             i;                                      // General purpose counter 
     1897        double                  s;                                      // Sample 
     1898        double                  fs;                                     // Filtered sample 
     1899        double                  *fbuffer;                       // Filter buffer 
     1900        int                             nfbuffer;                       // length of the filter buffer 
     1901        double                  *outsig;                        // Temporary array for output signal 
     1902        double                  outavg;                         // Compute average of output signal 
     1903        double                  outmax;                         // Compute maximum of output signal 
     1904        double                  tracestart;                     // Start of the trace 
     1905        double                  traceend = 0;           // End of the trace 
     1906        int                             *samples;                       // Array of samples to process 
     1907        int                             nsamples = 0;           // Number of samples to process 
     1908        int                             samppos = 0;            // Position of the sample in the array; 
     1909 
     1910        /* Reserve memory for temporary output signal 
     1911         ********************************************/ 
     1912        outsig = ( double* ) malloc( sizeof( double ) * noutsig ); 
     1913        if( outsig == NULL ) 
     1914        { 
     1915                logit( "et", "ewhtmlemail: Unable to reserve memory for resampled signal\n" ); 
     1916        return -1; 
     1917        } 
     1918         
     1919         
     1920        /* Reserve memory for input samples 
     1921         **********************************/ 
     1922        // RSL note: tried the serialized option but this is better 
     1923        samples = ( int* ) malloc( sizeof( int ) * MAX_SAMPLES ); 
     1924        if( samples == NULL ) 
     1925        { 
     1926                logit( "et", "ewhtmlemail: Unable to allocate memory for sample buffer\n" ); 
     1927        return -1; 
     1928        } 
     1929        for( i = 0; i < MAX_SAMPLES; i++ ) samples[i] = 0; 
     1930         
     1931         
     1932        /* Isolate input samples in a single buffer 
     1933         ******************************************/ 
     1934        trace_header = (TRACE2_HEADER*)buffer; 
     1935        trptr = buffer; 
     1936        while( ( trace_header = ( TRACE2_HEADER* ) trptr ) < (TRACE2_HEADER*)(buffer + buflen) ) 
     1937        { 
     1938                // If necessary, swap bytes in tracebuf message 
     1939        if ( WaveMsg2MakeLocal( trace_header ) < 0 ) 
     1940        { 
     1941                        logit( "et", "ewhtmlemail: WaveMsg2MakeLocal error.\n" ); 
     1942                return -1; 
     1943                } 
     1944                 
     1945                // Update times 
     1946                if( trptr == buffer ) tracestart = trace_header->starttime; 
     1947                if( trace_header->endtime > traceend) traceend = trace_header->endtime; 
     1948                inrate = trace_header->samprate; 
     1949                 
     1950                // Skip the trace header 
     1951                trptr += sizeof( TRACE2_HEADER ); 
     1952                 
     1953                for( i = 0; i < trace_header->nsamp; i++ ) 
     1954                { 
     1955                        // Produce integer sample 
     1956                        if( strcmp( trace_header->datatype, "i2" ) == 0 || 
     1957                                        strcmp(trace_header->datatype, "s2")==0 ) 
     1958                        { 
     1959                                s = ( int ) (*((short*)(trptr))); 
     1960                                trptr += 2; 
     1961                        } 
     1962                        else 
     1963                        { 
     1964                                s = *( ( int* )( trptr ) ); 
     1965                                trptr += 4; 
     1966                        } 
     1967                         
     1968                        // Compute position of the sample in the sample array 
     1969                        samppos = ( int )( ( trace_header->starttime  
     1970                                        + ( double ) i / trace_header->samprate - tracestart ) * 
     1971                                        trace_header->samprate ); 
     1972                                         
     1973                        if( samppos < 0 || samppos >= MAX_SAMPLES ) 
     1974                                continue; 
     1975                                         
     1976                        // Store sample in array 
     1977                        samples[samppos] = s; 
     1978                        if( samppos > nsamples ) nsamples = samppos; 
     1979                } 
     1980        } 
     1981         
     1982         
     1983        /* Prepare filter buffer 
     1984         ***********************/ 
     1985        outrate = ( double ) noutsig / ( endtime - starttime ); // Output sample rate 
     1986        nfbuffer = ( int )( inrate / outrate / 2 + 0.5 ); // Length of the filter buffer 
     1987        fbuffer = ( double* ) malloc( sizeof( double ) * nfbuffer ); 
     1988        if( fbuffer == NULL ) 
     1989        { 
     1990                logit( "et", "ewhtmlemail: Unable to allocate memory for filter buffer\n" ); 
     1991        return -1; 
     1992        } 
     1993        if( Debug ) logit("o", "Filter settings:  " 
     1994                        "Input rate: %f    Output rate: %f    Buffer length: %d\n",  
     1995                        inrate, outrate, nfbuffer ); 
     1996         
     1997         
     1998        /* Filter signal with array buffer 
     1999         *********************************/ 
     2000        int incounter = 0; 
     2001        int outcounter = 0; 
     2002        double stime; 
     2003        for( i = 0; i < nsamples; i++ ) 
     2004        { 
     2005                //printf("%d ",samples[i]); 
     2006                fs = fbuffer_add( fbuffer, nfbuffer, ( double ) samples[i] ); 
     2007                incounter++; 
     2008                 
     2009                // Check if sample can be used for output signal 
     2010                if( incounter % ( 2* nfbuffer ) == 0 ) 
     2011                { 
     2012                        // This sample should be considered, check its time stamp 
     2013                        stime = tracestart + ( double ) i / inrate; 
     2014                        if( stime >= starttime && stime <= endtime ) 
     2015                        { 
     2016                                // The sample is ok for output 
     2017                                outsig[outcounter++] = fs; 
     2018                                 
     2019                        } 
     2020                } 
     2021                 
     2022        } 
     2023 
     2024 
     2025         
     2026        /* Remove average of output signal 
     2027         *********************************/ 
     2028        outavg = 0; 
     2029        outmax = 0; 
     2030        for( i = 0; i < noutsig; i++ ) 
     2031        { 
     2032                outavg += outsig[i]; 
     2033                if( outsig[i] > outmax || outsig[i] < -outmax ) outmax = outsig[i]; 
     2034        } 
     2035        outavg /= ( double ) noutsig; 
     2036        outmax -= outavg; 
     2037        for(i = 0; i < noutsig; i++ ) 
     2038                outarray[i] = ( int ) ( ( outsig[i] - outavg ) / outmax * ( double ) outamp + 0.5 ); 
     2039         
     2040         
     2041         
     2042        // free memory 
     2043        free( fbuffer ); 
     2044        free( outsig ); 
     2045        free( samples ); 
     2046        return 1; 
     2047         
     2048} 
     2049 
     2050/* Add a new sample to the buffer filter and compute output */ 
     2051double fbuffer_add( double *fbuffer, int nfbuffer, double s ) 
     2052{ 
     2053        int i; 
     2054        double out = 0; 
     2055         
     2056        // circulate buffer 
     2057        for( i = 1; i < nfbuffer; i++ ) 
     2058                fbuffer[i - 1] = fbuffer[i]; 
     2059         
     2060        // add sample to buffer 
     2061        fbuffer[nfbuffer - 1] = s; 
     2062         
     2063        // compute filter output by averaging buffer 
     2064        for( i = 0; i < nfbuffer; i++ ) 
     2065                out += fbuffer[i]; 
     2066        out /= ( double ) nfbuffer; 
     2067         
     2068        return out; 
     2069} 
     2070 
     2071 
     2072 
     2073/**************************************************************************************** 
     2074 * trb2gif: Takes a buffer with tracebuf2 messages and produces a gif image with the    * 
     2075 *          corresponding trace                                                         * 
     2076 ****************************************************************************************/ 
     2077int trbf2gif( char *buf, int buflen, gdImagePtr gif, double starttime, double endtime, 
     2078                int fcolor, int bcolor ) 
     2079{ 
     2080        TRACE2_HEADER   *trace_header;  // Pointer to the header of the current trace 
     2081        char                    *trptr;                 // Pointer to the current sample 
     2082        double                  sampavg;                // To compute average value of the samples 
     2083        int                             nsampavg;               // Number of samples considered for the average 
     2084        double                  sampmax;                // To compute maximum value 
     2085        int                     i;                              // General purpose counter 
     2086        gdPointPtr              pol;                    // Polygon pointer 
     2087        int                             npol;                   // Number of samples in the polygon 
     2088        double                  xscale;                 // X-Axis scaling factor 
     2089        double                  dt;                             // Time interval between two consecutive samples 
     2090         
     2091         
     2092 
     2093         
     2094        // Reserve memory for polygon points //TODO Make this dynamic 
     2095        pol = ( gdPointPtr ) malloc( MAX_POL_LEN * sizeof( gdPoint ) ); 
     2096        if( pol == NULL ) 
     2097        { 
     2098                logit( "et", "trbf2gif: Unable to reserve memory for plotting trace.\n" ); 
     2099        return -1; 
     2100        } 
     2101        npol = 0; 
     2102         
     2103        // Initialize trace pointer 
     2104        trptr = buf;  
     2105         
     2106        // Initialize maximum counter to minimum integer 
     2107        sampmax = 0; 
     2108        sampavg = 0; 
     2109         
     2110        // Compute x-axis scale factor in pixels/second 
     2111        xscale = ( double ) gif->sx / ( endtime - starttime ); 
     2112         
     2113        // Cycle to process each trace an draw it on the gif image 
     2114        while( ( trace_header = ( TRACE2_HEADER* ) trptr ) < (TRACE2_HEADER*)(buf + buflen) ) 
     2115        { 
     2116                // Compute time between consecutive samples 
     2117                dt = ( trace_header->endtime - trace_header->starttime ) / 
     2118                                ( double ) trace_header->nsamp; 
     2119         
     2120                // If necessary, swap bytes in tracebuf message 
     2121        if ( WaveMsg2MakeLocal( trace_header ) < 0 ) 
     2122        { 
     2123                        logit( "et", "trbf2gif: WaveMsg2MakeLocal error.\n" ); 
     2124                        free( pol ); 
     2125            return -1; 
     2126                } 
     2127                 
     2128                // Store samples in polygon 
     2129                // This procedure saves all the samples of this trace on the polygon 
     2130                // It also stores the maximum value and average values of the samples 
     2131                // for correcting the polygon later 
     2132                 
     2133                // Skip the trace header 
     2134                trptr += sizeof( TRACE2_HEADER ); 
     2135                 
     2136                // Process samples 
     2137                if( strcmp( trace_header->datatype, "i2" ) == 0 || 
     2138                                strcmp(trace_header->datatype, "s2")==0 ) 
     2139            {    
     2140                // Short samples 
     2141                        for( i = 0; i < trace_header->nsamp; i++, npol++, trptr += 2 ) 
     2142                        { 
     2143                                // Compute x coordinate 
     2144                                pol[npol].x = ( int )( ( trace_header->starttime - starttime + 
     2145                                        ( double ) i * dt ) * xscale ); 
     2146                         
     2147                        // Compute raw y coordinate without scaling or de-averaging 
     2148                                pol[npol].y = ( int ) (*((short*)(trptr))); 
     2149                                 
     2150                                // Add sample to average counter 
     2151                                sampavg += ( double ) pol[npol].y; 
     2152                                nsampavg++; // Increments number of samples to consider for average 
     2153                                 
     2154                                // Consider sample for maximum (absolute) value 
     2155                                if( pol[npol].y > sampmax || pol[npol].y < -sampmax ) sampmax = pol[npol].y; 
     2156                        } 
     2157                } 
     2158                else if( strcmp( trace_header->datatype, "i4" ) == 0 || 
     2159                                strcmp(trace_header->datatype, "s4")==0 ) 
     2160                { 
     2161                // Integer samples 
     2162                        for( i = 0; i < trace_header->nsamp; i++, npol++, trptr += 4 ) 
     2163                        { 
     2164                                // Compute x coordinate 
     2165                                pol[npol].x = ( int )( ( trace_header->starttime - starttime + 
     2166                                        ( double ) i * dt ) * xscale ); 
     2167                         
     2168                        // Compute raw y coordinate without scaling or de-averaging 
     2169                                pol[npol].y = *((int*)(trptr)); 
     2170                                 
     2171                                // Add sample to average counter 
     2172                                sampavg += ( double ) pol[npol].y; 
     2173                                nsampavg++; // Increments number of samples to consider for average 
     2174                                 
     2175                                // Consider sample for maximum (non-absolute) value 
     2176                                if( pol[npol].y > sampmax || pol[npol].y < -sampmax ) sampmax = pol[npol].y; 
     2177                                 
     2178                                //printf("%d ", pol[npol].y); 
     2179                                //printf("samp: %d  avg: %f  max: %f\n",pol[npol].y,sampavg,sampmax); 
     2180                        } 
     2181                        //printf("\n"); 
     2182                } 
     2183                else 
     2184                { 
     2185                        // Unknown type of samples 
     2186                        logit( "et", "trbf2gif: Uknown type of samples\n" ); 
     2187                        free( pol ); 
     2188            return -1; 
     2189                } 
     2190                // At this point, the polygon is populated with samples from this trace 
     2191                // The sampmax, sampavg and nsampavg variables are also updated but have not 
     2192                // yet been applied to correct the polygon 
     2193        } // End of trace cycle 
     2194         
     2195        // Remove average from samples and normalize 
     2196        sampavg /= ( double ) nsampavg; // Compute final sample average 
     2197        sampmax -= sampavg; // Correct sample maximum with average; 
     2198        //printf("Buflen: %d   Avg: %f   Max: %f\n",buflen, sampavg,sampmax); 
     2199        for( i = 0; i < npol; i++ ) { 
     2200                pol[i].y = ( int ) ( gif->sy / 2 ) - 
     2201                                ( int )( ( ( double ) pol[i].y - sampavg ) / sampmax * ( double ) gif->sy / 2 ); 
     2202                //printf("(%d,%d) ",pol[i].x,pol[i].y); 
     2203        } 
     2204        //printf("\n"); 
     2205                                 
     2206        // Clear image 
     2207        gdImageFilledRectangle( gif, 0, 0, gif->sx, gif->sy, bcolor ); 
     2208                                 
     2209        // Draw poly line 
     2210        gdImagePolyLine( gif, pol, npol, fcolor ); 
     2211         
     2212         
     2213        // Free polygon memory 
     2214        free( pol ); 
     2215        return 1; 
     2216} 
     2217 
     2218 
     2219 
     2220 
     2221 
     2222/**************************************************************************************** 
     2223 * trb2gif: Plots a pick as a vertical line in the image. Includes the phase            * 
     2224 ****************************************************************************************/ 
     2225int pick2gif(gdImagePtr gif, double picktime, char pickphase,  
     2226                double starttime, double endtime, int fcolor) 
     2227{ 
     2228        // Draw vertical line 
     2229        int pickpos = ( int ) ( ( double ) gif->sx / ( endtime - starttime ) * 
     2230                        ( picktime - starttime ) + 0.5 ); 
     2231        gdImageLine(gif, pickpos, 0, pickpos, gif->sy, fcolor); 
     2232         
     2233        // Draw phase character 
     2234        gdImageChar(gif, gdFontSmall, pickpos - 8, 1, pickphase, fcolor); 
     2235         
     2236        return 1; 
     2237} 
     2238 
     2239 
     2240 
     2241 
     2242 
     2243 
     2244 
     2245/**************************************************************************************** 
     2246 * Utility Functions                                                                    * 
     2247 ****************************************************************************************/ 
     2248 
     2249// Draw a poly line 
     2250void gdImagePolyLine( gdImagePtr im, gdPointPtr pol, int n, int c ) 
     2251{ 
     2252        int i; 
     2253        for( i = 0; i < ( n - 1 ); i++ ) 
     2254                gdImageLine( im, pol[i].x, pol[i].y, pol[i + 1].x, pol[i + 1].y, c); 
     2255} 
     2256 
     2257 
     2258 
     2259 
  • trunk/src/reporting/ewhtmlemail/ewhtmlemail.css

    r4378 r5055  
    6262   width: 600px; 
    6363} 
    64  
  • trunk/src/reporting/ewhtmlemail/ewhtmlemail.d

    r5047 r5055  
    2525#             know which waveforms are to be search from the waveservers and 
    2626#             also to plot the stations in the static google map. 
    27  site_file    cvarg.hinv 
     27 site_file    memphis2.hinv 
    2828                          
    2929 
     
    3333#            This configuration allows creating a folder with html files for the 
    3434#            detected seismic events. 
    35  HTMLFile        /home/earthworm/ewhtmlemail/emailfile 
     35 HTMLFile        temp/emailfile 
    3636  
    3737 
     
    6767 
    6868# List of email recipients 
    69  EmailRecipient recipient@email.com 
     69 EmailRecipient test@mail.com 
    7070  
    7171  
     
    7575#             css file. Please consult the example ewhtmlemail.css file for the 
    7676#             ids and class names. 
    77  StyleFile       /home/earthworm/params/ewhtmlemail.css 
     77 StyleFile       ewhtmlemail.css 
    7878 
    7979 
     
    9999 TimeMargin     10.0 
    100100  
     101 
    101102 # MaxDuration - is the maximum duration of the trace from origin_time - TimeMargin to endtime+ TimeMargin 
    102103 # if trace is longer than this in length, then endtime is set to  origin_time - TimeMargin + MaxDuration  
    103104 MaxDuration    60.0   # defaults to 144 seconds, new feature 
    104105 
    105   
    106   
     106 
     107 #UseGIF                                # Not yet functional 
     108 #TraceWidth   1200             # Sets width of traces (Default 600) 
     109 #TraceHeight   200             # Sets height of traces (Default 60) 
     110 # Note that changing width or height is limited to 300 000 points for google charts 
     111 # In addition, the css file should be changed accordingly to avoid resizing 
    107112  
    108113                          
  • trunk/src/reporting/ewhtmlemail/makefile.nt

    r4831 r5055  
    3737    $L\mem_circ_queue.obj $L\kom.obj $L\getsysname_ew.obj $L\getutil.obj $L\rw_mag.obj\ 
    3838    $L\logit_mt.obj $L\read_arc.obj $L\time_ew.obj $L\threads_ew.obj $L\transport.obj \ 
    39     $L\site.obj $L\sleep_ew.obj $L\sema_ew.obj $L\dirops_ew.obj -out:$B\$(APP).exe 
     39    $L\site.obj $L\sleep_ew.obj $L\sema_ew.obj $L\dirops_ew.obj \ 
     40    $L\gd.obj $L\gdfonts.obj -out:$B\$(APP).exe 
    4041 
    4142.c.obj: 
  • trunk/src/reporting/ewhtmlemail/makefile.sol

    r4945 r5055  
    1313        $L/transport.o $L/sleep_ew.o $L/time_ew.o \ 
    1414        $L/read_arc.o $L/chron3.o $L/fleng.o $L/ws_clientII.o \ 
    15         $L/socket_ew_common.o $L/socket_ew.o $L/swap.o $L/rw_mag.o 
     15        $L/socket_ew_common.o $L/socket_ew.o $L/swap.o $L/rw_mag.o \ 
     16        $L/gd.o $L/gdfonts.o 
    1617 
    1718all: 
  • trunk/src/reporting/ewhtmlemail/makefile.ux

    r4877 r5055  
    1313        $L/transport.o $L/sleep_ew.o $L/time_ew.o \ 
    1414        $L/read_arc.o $L/chron3.o $L/fleng.o $L/ws_clientII.o \ 
    15         $L/socket_ew_common.o $L/socket_ew.o $L/swap.o $L/rw_mag.o 
     15        $L/socket_ew_common.o $L/socket_ew.o $L/swap.o $L/rw_mag.o \ 
     16        $L/gd.o $L/gdfonts.o 
    1617 
    1718all: 
Note: See TracChangeset for help on using the changeset viewer.