| 1 | /* $Id: kHtmlPC.cpp,v 1.3 2000-02-18 12:42:07 bird Exp $ */ | 
|---|
| 2 | /* | 
|---|
| 3 | * kHtmlPC - Special-purpose HTML/SQL preprocessor. | 
|---|
| 4 | * | 
|---|
| 5 | * Copyright (c) 1999 knut st. osmundsen | 
|---|
| 6 | * | 
|---|
| 7 | */ | 
|---|
| 8 |  | 
|---|
| 9 | /******************************************************************************* | 
|---|
| 10 | *   Defined Constants                                                          * | 
|---|
| 11 | *******************************************************************************/ | 
|---|
| 12 | #define ErrorDescCase(errorcode)  case errorcode: return formatMessage(#errorcode) | 
|---|
| 13 | #define TAG_PARAMETER_LIST                        \ | 
|---|
| 14 | const kTag                        &tag,       \ | 
|---|
| 15 | kLIFO<kFileEntry>                 &lifoFile,  \ | 
|---|
| 16 | kLIFO<kFileEntry>                 &lifoUsed,  \ | 
|---|
| 17 | kLIFO<kVariableEntry>             &lifoVar,   \ | 
|---|
| 18 | kLIFO2<kSqlEntry, kVariableEntry> &lifoSql,   \ | 
|---|
| 19 | kFileEntry                      * &pCurFile,  \ | 
|---|
| 20 | int                               &i,         \ | 
|---|
| 21 | FILE                              *phLog | 
|---|
| 22 |  | 
|---|
| 23 | #define TAG_PARAMETERS tag, lifoFile, lifoUsed, lifoVar, lifoSql, pCurFile, i, phLog | 
|---|
| 24 | #define TAG_PARAMETER_LIST_UNREF                       \ | 
|---|
| 25 | int f = phLog || i || pCurFile || &lifoFile || \ | 
|---|
| 26 | &lifoUsed || &lifoVar || &lifoSql || &tag; \ | 
|---|
| 27 | f = f | 
|---|
| 28 |  | 
|---|
| 29 | #ifdef __EMX__ | 
|---|
| 30 | #define max(a,b) (((a) > (b)) ? (a) : (b)) | 
|---|
| 31 | #define min(a,b) (((a) < (b)) ? (a) : (b)) | 
|---|
| 32 | #define _System | 
|---|
| 33 | #endif | 
|---|
| 34 |  | 
|---|
| 35 | #define TRUE  1 | 
|---|
| 36 | #define FALSE 0 | 
|---|
| 37 | #define CCHMAXPATH 260 | 
|---|
| 38 |  | 
|---|
| 39 |  | 
|---|
| 40 | /******************************************************************************* | 
|---|
| 41 | *   Structures and Typedefs                                                    * | 
|---|
| 42 | *******************************************************************************/ | 
|---|
| 43 | typedef unsigned long BOOL; | 
|---|
| 44 | typedef struct _POINTL | 
|---|
| 45 | { | 
|---|
| 46 | long x; | 
|---|
| 47 | long y; | 
|---|
| 48 | } POINTL, *PPOINTL; | 
|---|
| 49 |  | 
|---|
| 50 |  | 
|---|
| 51 | /******************************************************************************* | 
|---|
| 52 | *   Header Files                                                               * | 
|---|
| 53 | *******************************************************************************/ | 
|---|
| 54 | #include <stdio.h> | 
|---|
| 55 | #include <stdlib.h> | 
|---|
| 56 | #include <string.h> | 
|---|
| 57 | #include <signal.h> | 
|---|
| 58 | #include <malloc.h> | 
|---|
| 59 | #ifdef __EMX__ | 
|---|
| 60 | #include <math.h> | 
|---|
| 61 | #undef _NAN | 
|---|
| 62 | static double _NAN = (0.0/0.0); | 
|---|
| 63 | #else | 
|---|
| 64 | #include <float.h> | 
|---|
| 65 | #endif | 
|---|
| 66 | #include <assert.h> | 
|---|
| 67 | /* gifdraw */ | 
|---|
| 68 | extern "C" | 
|---|
| 69 | { | 
|---|
| 70 | #include "gd/gd.h" | 
|---|
| 71 | #include "gd/gdfontg.h" | 
|---|
| 72 | #include "gd/gdfontl.h" | 
|---|
| 73 | #include "gd/gdfonts.h" | 
|---|
| 74 | /* Y wrappers; LB = origo at Left Botton corner */ | 
|---|
| 75 | #define gdImageLineLB(im,x1,y1,x2,y2,cl) gdImageLine(im,x1,gdImageSY(im)-(y1),x2,gdImageSY(im)-(y2),cl) | 
|---|
| 76 | #define gdImageStringLB(im,f,x,y,s,cl) gdImageString(im,f,x,gdImageSY(im)-(y),s,cl) | 
|---|
| 77 | #define gdImageStringUpLB(im,f,x,y,s,cl) gdImageStringUp(im,f,x,gdImageSY(im)-(y),s,cl) | 
|---|
| 78 | } | 
|---|
| 79 |  | 
|---|
| 80 | #include "kLIFO.h" | 
|---|
| 81 | #include "kList.h" | 
|---|
| 82 | #include "kHtmlPC.h" | 
|---|
| 83 | #include "db.h" | 
|---|
| 84 |  | 
|---|
| 85 | /*@Struct*********************************************************************** | 
|---|
| 86 | *   Structures and Typedefs                                                    * | 
|---|
| 87 | *******************************************************************************/ | 
|---|
| 88 | typedef struct _GraphCallBackParameters | 
|---|
| 89 | { | 
|---|
| 90 | kGraph             *pGraph; | 
|---|
| 91 | kGraphDataSet      *pDataSet; | 
|---|
| 92 | kGraphData         *pData; | 
|---|
| 93 | kGraph::enmType     enmTypeCd; | 
|---|
| 94 | long                lSeqNbr; | 
|---|
| 95 | char               *pszLegend; | 
|---|
| 96 | char               *pszColor; | 
|---|
| 97 | } GRAPHCALLBACKPARAM, *PGRAPHCALLBACKPARAM; | 
|---|
| 98 |  | 
|---|
| 99 |  | 
|---|
| 100 |  | 
|---|
| 101 | /******************************************************************************* | 
|---|
| 102 | *   Global Variables                                                           * | 
|---|
| 103 | *******************************************************************************/ | 
|---|
| 104 | static FILE  *phLog = NULL; | 
|---|
| 105 |  | 
|---|
| 106 |  | 
|---|
| 107 | /******************************************************************************* | 
|---|
| 108 | *   Internal Functions                                                         * | 
|---|
| 109 | *******************************************************************************/ | 
|---|
| 110 | extern "C" void      handler(int sig); | 
|---|
| 111 | static void          syntax(void); | 
|---|
| 112 | static void          openLog(void); | 
|---|
| 113 | static void          closeLog(void); | 
|---|
| 114 | static unsigned long processFile(const char *pszFilenamem, const POPTIONS pOptions); | 
|---|
| 115 | static unsigned long tagEndkSql(TAG_PARAMETER_LIST); | 
|---|
| 116 | static unsigned long tagkSql(TAG_PARAMETER_LIST); | 
|---|
| 117 | static unsigned long tagkTemplate(TAG_PARAMETER_LIST, FILE * &phFile, const POPTIONS pOptions); | 
|---|
| 118 | static unsigned long tagkInclude(TAG_PARAMETER_LIST); | 
|---|
| 119 | static unsigned long tagkGraph(TAG_PARAMETER_LIST, const POPTIONS pOptions); | 
|---|
| 120 | static unsigned long tagkDefine(TAG_PARAMETER_LIST); | 
|---|
| 121 | static unsigned long tagkUndef(TAG_PARAMETER_LIST); | 
|---|
| 122 | static unsigned long tagkIf(TAG_PARAMETER_LIST); | 
|---|
| 123 | static unsigned long tagkElse(TAG_PARAMETER_LIST); | 
|---|
| 124 | static unsigned long tagkEndif(TAG_PARAMETER_LIST); | 
|---|
| 125 |  | 
|---|
| 126 | static BOOL          rebuildFileLIFO(kLIFO<kFileEntry> &lifoFile, kLIFO<kFileEntry> &lifoUsed, const kFileEntry *pFileEntryTop); | 
|---|
| 127 | static char         *dupeString(const char *psz); | 
|---|
| 128 | #if 0 | 
|---|
| 129 | inline char          upcase(char ch); | 
|---|
| 130 | static char         *stristr(const char *pszStr, const char *pszSubStr); | 
|---|
| 131 | static char         *trim(char *psz); | 
|---|
| 132 | static char         *ltrim(char *psz); | 
|---|
| 133 | static const char   *ltrim(const char *psz); | 
|---|
| 134 | static char         *ltrimL(char *psz); | 
|---|
| 135 | #endif | 
|---|
| 136 | static const char   *ltrimL(const char *psz); | 
|---|
| 137 | static long _System  dbFetchCallBack(const char *pszValue, const char *pszFieldName, void *pvUser); | 
|---|
| 138 | long _System         dbDataSetCallBack(const char *pszValue, const char *pszFieldName, void *pvUser); | 
|---|
| 139 | long _System         dbGraphCallBack(const char *pszValue, const char *pszFieldName, void *pvUser); | 
|---|
| 140 |  | 
|---|
| 141 |  | 
|---|
| 142 | /** | 
|---|
| 143 | * Main function. | 
|---|
| 144 | * @returns   Number of errors | 
|---|
| 145 | * @param     argc  Argument count. | 
|---|
| 146 | * @param     argv  Argument array. | 
|---|
| 147 | */ | 
|---|
| 148 | int main(int argc, char **argv) | 
|---|
| 149 | { | 
|---|
| 150 | int             argi; | 
|---|
| 151 | BOOL            fFatal = FALSE; | 
|---|
| 152 | unsigned long   ulRc = 0; | 
|---|
| 153 | char           *pszHost     = "localhost"; | 
|---|
| 154 | char           *pszDatabase = "Odin32"; | 
|---|
| 155 | char           *pszUser     = "root"; | 
|---|
| 156 | char           *pszPasswd   = ""; | 
|---|
| 157 | char            szPathName[CCHMAXPATH]; | 
|---|
| 158 | OPTIONS         options = {"."}; | 
|---|
| 159 |  | 
|---|
| 160 |  | 
|---|
| 161 | /* signal handler */ | 
|---|
| 162 | if (SIG_ERR == signal(SIGBREAK, handler) | 
|---|
| 163 | || SIG_ERR == signal(SIGTERM, handler) | 
|---|
| 164 | || SIG_ERR == signal(SIGINT, handler) | 
|---|
| 165 | ) | 
|---|
| 166 | fprintf(stderr, "Error installing signalhandler..."); | 
|---|
| 167 |  | 
|---|
| 168 |  | 
|---|
| 169 | /************************************************************************** | 
|---|
| 170 | * parse arguments. | 
|---|
| 171 | * options:  -h or -?     help | 
|---|
| 172 | *           -b:<basepath> Basepath for output files. | 
|---|
| 173 | *           -d:<dbname>   Database name | 
|---|
| 174 | *           -p:<passwd>   Password | 
|---|
| 175 | *           -u:<user>     Userid | 
|---|
| 176 | *           -h:<host>     Hostname/IP-address | 
|---|
| 177 | **************************************************************************/ | 
|---|
| 178 | if (argc == 1) | 
|---|
| 179 | syntax(); | 
|---|
| 180 | argi = 1; | 
|---|
| 181 | while (argi < argc && !fFatal) | 
|---|
| 182 | { | 
|---|
| 183 | if(argv[argi][0] == '-' || argv[argi][0] == '/') | 
|---|
| 184 | { | 
|---|
| 185 | switch (argv[argi][1]) | 
|---|
| 186 | { | 
|---|
| 187 | case 'b': | 
|---|
| 188 | case 'B': | 
|---|
| 189 | printf("%s\n", argv[argi]); | 
|---|
| 190 | if (argv[argi][2] == ':') | 
|---|
| 191 | { | 
|---|
| 192 | if (_fullpath(&szPathName[0], &argv[argi][3], sizeof(szPathName)) != NULL) | 
|---|
| 193 | options.pszBaseDir = &szPathName[0]; | 
|---|
| 194 | else | 
|---|
| 195 | { | 
|---|
| 196 | fprintf(stderr, "error: basepath '%s' don't exists\n", &argv[argi][3]); | 
|---|
| 197 | fFatal = TRUE; | 
|---|
| 198 | } | 
|---|
| 199 | } | 
|---|
| 200 | else | 
|---|
| 201 | { | 
|---|
| 202 | fprintf(stderr, "error: option '-b:' requires a directory name.\n"); | 
|---|
| 203 | fFatal = TRUE; | 
|---|
| 204 | } | 
|---|
| 205 | break; | 
|---|
| 206 |  | 
|---|
| 207 | case 'd': | 
|---|
| 208 | case 'D': | 
|---|
| 209 | if (argv[argi][2] == ':') | 
|---|
| 210 | pszDatabase = &argv[argi][3]; | 
|---|
| 211 | else | 
|---|
| 212 | { | 
|---|
| 213 | fprintf(stderr, "error: option '-d:' requires database name.\n"); | 
|---|
| 214 | fFatal = TRUE; | 
|---|
| 215 | } | 
|---|
| 216 | break; | 
|---|
| 217 |  | 
|---|
| 218 | case 'h': | 
|---|
| 219 | case 'H': | 
|---|
| 220 | if (argv[argi][2] == ':') | 
|---|
| 221 | { | 
|---|
| 222 | pszHost = &argv[argi][3]; | 
|---|
| 223 | break; | 
|---|
| 224 | } | 
|---|
| 225 | case '?': | 
|---|
| 226 | syntax(); | 
|---|
| 227 | return 0; | 
|---|
| 228 |  | 
|---|
| 229 | case 'p': | 
|---|
| 230 | case 'P': | 
|---|
| 231 | if (argv[argi][2] == ':') | 
|---|
| 232 | pszPasswd = &argv[argi][3]; | 
|---|
| 233 | else | 
|---|
| 234 | { | 
|---|
| 235 | fprintf(stderr, "error: option '-p:' requires password.\n"); | 
|---|
| 236 | fFatal = TRUE; | 
|---|
| 237 | } | 
|---|
| 238 | break; | 
|---|
| 239 |  | 
|---|
| 240 | case 'u': | 
|---|
| 241 | case 'U': | 
|---|
| 242 | if (argv[argi][2] == ':') | 
|---|
| 243 | pszUser = &argv[argi][3]; | 
|---|
| 244 | else | 
|---|
| 245 | { | 
|---|
| 246 | fprintf(stderr, "error: option '-u:' requires userid.\n"); | 
|---|
| 247 | fFatal = TRUE; | 
|---|
| 248 | } | 
|---|
| 249 | break; | 
|---|
| 250 |  | 
|---|
| 251 | /* | 
|---|
| 252 | options.fSomeOption = argv[argi][2] != '-'; | 
|---|
| 253 | break; | 
|---|
| 254 | */ | 
|---|
| 255 |  | 
|---|
| 256 | default: | 
|---|
| 257 | fprintf(stderr, "incorrect parameter. (argi=%d, argv[argi]=%s)\n", argi, argv[argi]); | 
|---|
| 258 | fFatal = TRUE; | 
|---|
| 259 | break; | 
|---|
| 260 | } | 
|---|
| 261 | } | 
|---|
| 262 | else | 
|---|
| 263 | { | 
|---|
| 264 | if (phLog == NULL) | 
|---|
| 265 | openLog(); | 
|---|
| 266 | if (dbConnect(pszHost, pszUser, pszPasswd, pszDatabase)) | 
|---|
| 267 | { | 
|---|
| 268 | ulRc += processFile(argv[argi], &options); | 
|---|
| 269 | dbDisconnect(); | 
|---|
| 270 | } | 
|---|
| 271 | else | 
|---|
| 272 | fprintf(phLog, "Error connecting to database.\n"); | 
|---|
| 273 | } | 
|---|
| 274 | argi++; | 
|---|
| 275 | } | 
|---|
| 276 |  | 
|---|
| 277 | /* close the log */ | 
|---|
| 278 | closeLog(); | 
|---|
| 279 |  | 
|---|
| 280 | /* warn if error during processing. */ | 
|---|
| 281 | if (!fFatal) | 
|---|
| 282 | fprintf(stderr, "kHTMLPreCompiler compleated with %ld error%s and %ld warning%s.\n", | 
|---|
| 283 | ulRc & 0x0000ffffUL, (ulRc & 0x0000ffffUL) != 1 ? "s" : "", | 
|---|
| 284 | ulRc >> 16, (ulRc >> 16) != 1 ? "s" : "" | 
|---|
| 285 | ); | 
|---|
| 286 | return (int)(ulRc & 0x0000ffff); | 
|---|
| 287 | } | 
|---|
| 288 |  | 
|---|
| 289 |  | 
|---|
| 290 | /** | 
|---|
| 291 | * signal handler.... | 
|---|
| 292 | * @param     sig | 
|---|
| 293 | * @remark    Needs to flush files before termination. (debugging purpose) | 
|---|
| 294 | */ | 
|---|
| 295 | void handler(int sig) | 
|---|
| 296 | { | 
|---|
| 297 | fprintf(stderr, "\n\t!signal %d!\n", sig); | 
|---|
| 298 | flushall(); | 
|---|
| 299 | dbDisconnect(); | 
|---|
| 300 | exit(-1); | 
|---|
| 301 | } | 
|---|
| 302 |  | 
|---|
| 303 | /** | 
|---|
| 304 | * Display syntax. | 
|---|
| 305 | */ | 
|---|
| 306 | static void syntax(void) | 
|---|
| 307 | { | 
|---|
| 308 | printf("\n" | 
|---|
| 309 | "kHtmlPC v%01d.%02d - General-purpose HTML precompiler.\n" | 
|---|
| 310 | "-------------------------------------------------\n" | 
|---|
| 311 | "syntax: kHtmlPc.exe  [-h|-?] [options] [file1 [file2 [..]]\n" | 
|---|
| 312 | "\n" | 
|---|
| 313 | "    -h or -?      Syntax help. (this)\n" | 
|---|
| 314 | "    -h:<hostname> Database server hostname.     default: localhost\n" | 
|---|
| 315 | "    -u:<username> Username on the server.       default: root\n" | 
|---|
| 316 | "    -p:<password> Password.                     default: <empty>\n" | 
|---|
| 317 | "    -d:<database> Database to use.              default: Odin32\n" | 
|---|
| 318 | "\n" | 
|---|
| 319 | "\n" | 
|---|
| 320 | "Copyright (c) 1999 knut st. osmundsen (knut.stange.osmundsen@pmsc.no)", | 
|---|
| 321 | VER_MAJOR, VER_MINOR | 
|---|
| 322 | ); | 
|---|
| 323 | } | 
|---|
| 324 |  | 
|---|
| 325 |  | 
|---|
| 326 | /** | 
|---|
| 327 | * Opens log file. Currently this we don't use a logfile, stderr is our logfile. | 
|---|
| 328 | */ | 
|---|
| 329 | static void openLog(void) | 
|---|
| 330 | { | 
|---|
| 331 | #if 0 | 
|---|
| 332 | if (phLog == NULL) | 
|---|
| 333 | { | 
|---|
| 334 | phLog = fopen("APIImport.Log", "w"); | 
|---|
| 335 | if (phLog == NULL) | 
|---|
| 336 | { | 
|---|
| 337 | fprintf(stderr,"error occured while opening log file - will use stderr instead.\n"); | 
|---|
| 338 | phLog = stderr; | 
|---|
| 339 | } | 
|---|
| 340 | } | 
|---|
| 341 | #else | 
|---|
| 342 | phLog = stderr; | 
|---|
| 343 | #endif | 
|---|
| 344 | } | 
|---|
| 345 |  | 
|---|
| 346 |  | 
|---|
| 347 | /** | 
|---|
| 348 | * Closes the log. | 
|---|
| 349 | */ | 
|---|
| 350 | static void closeLog(void) | 
|---|
| 351 | { | 
|---|
| 352 | if (phLog != stderr && phLog != NULL) | 
|---|
| 353 | fclose(phLog); | 
|---|
| 354 | } | 
|---|
| 355 |  | 
|---|
| 356 |  | 
|---|
| 357 | /** | 
|---|
| 358 | * Preprocesses a file. | 
|---|
| 359 | * @returns   high word  Number of warnings. | 
|---|
| 360 | *            low  word  Number of errors; | 
|---|
| 361 | * @param     pszFilename  Pointer to filename. | 
|---|
| 362 | * @param     pOption      Pointer to the option struct. | 
|---|
| 363 | * @remark    Big function! | 
|---|
| 364 | */ | 
|---|
| 365 | static unsigned long processFile(const char *pszFilename, const POPTIONS pOptions) | 
|---|
| 366 | { | 
|---|
| 367 | unsigned long                      ulRc = 0; | 
|---|
| 368 | unsigned long                      ulRc2; | 
|---|
| 369 | FILE                              *phFile = NULL;       /* Current output file. */ | 
|---|
| 370 | kLIFO<kFileEntry>                  lifoFile, lifoUsed; | 
|---|
| 371 | kLIFO<kVariableEntry>              lifoVar;             /* tags not implemented yet... */ | 
|---|
| 372 | kLIFO2<kSqlEntry, kVariableEntry>  lifoSql; | 
|---|
| 373 | kFileEntry                        *pCurFile; | 
|---|
| 374 | const kVariableEntry              *pVariable = NULL; | 
|---|
| 375 | const char                        *psz; | 
|---|
| 376 | char                               szVariable[81]; | 
|---|
| 377 |  | 
|---|
| 378 | /* open initial file */ | 
|---|
| 379 | try | 
|---|
| 380 | { | 
|---|
| 381 | pCurFile = new kFileEntry(pszFilename); | 
|---|
| 382 | } | 
|---|
| 383 | catch (int errorcode) | 
|---|
| 384 | { | 
|---|
| 385 | fprintf(phLog, "error opening initial file. errorcode = %d\n", errorcode); | 
|---|
| 386 | return 0x00000001; | 
|---|
| 387 | } | 
|---|
| 388 |  | 
|---|
| 389 | /* loop on pCurFile */ | 
|---|
| 390 | while (pCurFile != NULL) | 
|---|
| 391 | { | 
|---|
| 392 | /* loop on curFile->pszCurrent */ | 
|---|
| 393 | while (pCurFile->pszCurrent != NULL && *pCurFile->pszCurrent != '\0') | 
|---|
| 394 | { | 
|---|
| 395 | /*********/ | 
|---|
| 396 | /* !kTag */ | 
|---|
| 397 | /*********/ | 
|---|
| 398 | if (pCurFile->pszCurrent[0] == '<' && pCurFile->pszCurrent[1] == '!') | 
|---|
| 399 | {   /* find end, replace variables and switch tag type. */ | 
|---|
| 400 | char  szTag[1024]; | 
|---|
| 401 | BOOL fQuote = FALSE; | 
|---|
| 402 | int  i = 0, j = 0; | 
|---|
| 403 |  | 
|---|
| 404 | /* copy tag and insert variables */ | 
|---|
| 405 | while ((fQuote || pCurFile->pszCurrent[i] != '>') && pCurFile->pszCurrent[i] != '\0' | 
|---|
| 406 | && j < (int)sizeof(szTag)) | 
|---|
| 407 | { | 
|---|
| 408 | fQuote = fQuote ? pCurFile->pszCurrent[i] != '"' : pCurFile->pszCurrent[i] == '"'; | 
|---|
| 409 | /* variable? */ | 
|---|
| 410 | if (pCurFile->pszCurrent[i] == '$' && pCurFile->pszCurrent[i+1] == '(') | 
|---|
| 411 | { | 
|---|
| 412 | psz = pCurFile->pszCurrent + i + 2; | 
|---|
| 413 | while (*psz != ')' && *psz != '\0' && (psz - &pCurFile->pszCurrent[i]) < (int)(sizeof(szVariable)-1)) | 
|---|
| 414 | psz++; | 
|---|
| 415 | if (*psz == ')') | 
|---|
| 416 | { | 
|---|
| 417 | strncpy(&szVariable[0], pCurFile->pszCurrent + i + 2, psz - &pCurFile->pszCurrent[i] - 2); | 
|---|
| 418 | szVariable[psz - &pCurFile->pszCurrent[i] - 2] = '\0'; | 
|---|
| 419 |  | 
|---|
| 420 | pVariable = lifoSql.findSub(&szVariable[0]); | 
|---|
| 421 | if (pVariable == NULL) | 
|---|
| 422 | pVariable = lifoVar.find(&szVariable[0]); | 
|---|
| 423 |  | 
|---|
| 424 | if (pVariable != NULL) | 
|---|
| 425 | { | 
|---|
| 426 | if(j + strlen(pVariable->getValue()) < sizeof(szTag)) | 
|---|
| 427 | {   /* copy variable value */ | 
|---|
| 428 | strcpy(&szTag[j], pVariable->getValue()); | 
|---|
| 429 | j += strlen(&szTag[j]) - 1; | 
|---|
| 430 | i += psz - &pCurFile->pszCurrent[i]; | 
|---|
| 431 | } | 
|---|
| 432 | else | 
|---|
| 433 | {   /* warning - complain, skip and continue */ | 
|---|
| 434 | fprintf(phLog, "%s(%ld) : warning: Variable '%s' out of space, increase the size of szTag.\n", | 
|---|
| 435 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, &szVariable[0]); | 
|---|
| 436 | szTag[j] = pCurFile->pszCurrent[i]; | 
|---|
| 437 | } | 
|---|
| 438 | } | 
|---|
| 439 | else | 
|---|
| 440 | {   /* warning - complain, skip and continue */ | 
|---|
| 441 | fprintf(phLog, "%s(%ld) : warning: Variable '%s' not defined.\n", | 
|---|
| 442 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, &szVariable[0]); | 
|---|
| 443 | szTag[j] = pCurFile->pszCurrent[i]; | 
|---|
| 444 | } | 
|---|
| 445 | } | 
|---|
| 446 | else | 
|---|
| 447 | {   /* error - complain, skip and continue. */ | 
|---|
| 448 | fprintf(phLog, "%s(%ld) : error: Missing left parenthese on variable expression\n", | 
|---|
| 449 | pCurFile->getFilename(), pCurFile->getLineNumber()+1); | 
|---|
| 450 | szTag[j] = pCurFile->pszCurrent[i]; | 
|---|
| 451 | } | 
|---|
| 452 | } | 
|---|
| 453 | else | 
|---|
| 454 | szTag[j] = pCurFile->pszCurrent[i]; | 
|---|
| 455 | /* next */ | 
|---|
| 456 | i++; | 
|---|
| 457 | j++; | 
|---|
| 458 | } | 
|---|
| 459 |  | 
|---|
| 460 |  | 
|---|
| 461 | /* copy ok? */ | 
|---|
| 462 | if (j < (int)sizeof(szTag) && pCurFile->pszCurrent[i] == '>') | 
|---|
| 463 | { | 
|---|
| 464 | szTag[j++] = '>'; | 
|---|
| 465 | szTag[j] = '\0'; | 
|---|
| 466 | i++; | 
|---|
| 467 | try | 
|---|
| 468 | { | 
|---|
| 469 | /* try create tag object */ | 
|---|
| 470 | kTag tag(&szTag[0]); | 
|---|
| 471 |  | 
|---|
| 472 | /* check for warning */ | 
|---|
| 473 | if (tag.queryWarning() != NULL) | 
|---|
| 474 | fprintf(phLog, "%s(%ld) : warning: tag warning - %s.\n", | 
|---|
| 475 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, tag.queryWarning()); | 
|---|
| 476 |  | 
|---|
| 477 |  | 
|---|
| 478 | /**************/ | 
|---|
| 479 | /**************/ | 
|---|
| 480 | /* tag switch */ | 
|---|
| 481 | /**************/ | 
|---|
| 482 | /**************/ | 
|---|
| 483 | ulRc2 = 0; | 
|---|
| 484 | if (tag.isTag("!kSql"))                         /* !kSql        */ | 
|---|
| 485 | ulRc2 = tagkSql(TAG_PARAMETERS); | 
|---|
| 486 | else if (tag.isTag("!/kSql"))                   /* !/kSql       */ | 
|---|
| 487 | ulRc2 = tagEndkSql(TAG_PARAMETERS); | 
|---|
| 488 | else if (tag.isTag("!kTemplate"))               /* !kTemplate   */ | 
|---|
| 489 | ulRc2 = tagkTemplate(TAG_PARAMETERS, phFile, pOptions); | 
|---|
| 490 | else if (tag.isTag("!kInclude"))                /* !kInclude    */ | 
|---|
| 491 | ulRc2 = tagkInclude(TAG_PARAMETERS); | 
|---|
| 492 | else if (tag.isTag("!kGraph"))                  /* !kGraph      */ | 
|---|
| 493 | ulRc2 = tagkGraph(TAG_PARAMETERS, pOptions); | 
|---|
| 494 | else if (tag.isTag("!kDefine"))                 /* !kDefine     */ | 
|---|
| 495 | ulRc2 = tagkDefine(TAG_PARAMETERS); | 
|---|
| 496 | else if (tag.isTag("!kUndef"))                  /* !kUndef      */ | 
|---|
| 497 | ulRc2 = tagkUndef(TAG_PARAMETERS); | 
|---|
| 498 | else if (tag.isTag("!kIf"))                     /* !kIf         */ | 
|---|
| 499 | ulRc2 = tagkIf(TAG_PARAMETERS); | 
|---|
| 500 | else if (tag.isTag("!kElse"))                   /* !kElse       */ | 
|---|
| 501 | ulRc2 = tagkElse(TAG_PARAMETERS); | 
|---|
| 502 | else if (tag.isTag("!kEndif"))                  /* !kEndif      */ | 
|---|
| 503 | ulRc2 = tagkEndif(TAG_PARAMETERS); | 
|---|
| 504 | else | 
|---|
| 505 | { | 
|---|
| 506 | if (phFile != NULL) | 
|---|
| 507 | fputc(*pCurFile->pszCurrent, phFile); /* if this proove to be very slow, we'll have to buffer writes better. */ | 
|---|
| 508 | pCurFile->pszCurrent++; | 
|---|
| 509 | } | 
|---|
| 510 |  | 
|---|
| 511 | /* if error occurred - skip and continue. */ | 
|---|
| 512 | if ((ulRc2 & 0x0000ffff) != 0) | 
|---|
| 513 | { | 
|---|
| 514 | if (phFile != NULL) | 
|---|
| 515 | fputc(*pCurFile->pszCurrent, phFile); /* if this proove to be very slow, we'll have to buffer writes better. */ | 
|---|
| 516 | pCurFile->pszCurrent++; | 
|---|
| 517 | } | 
|---|
| 518 | ulRc += ulRc2; | 
|---|
| 519 | } | 
|---|
| 520 | catch (kError::enmErrors enmErrorCd) | 
|---|
| 521 | { | 
|---|
| 522 | fprintf(phLog, "%s(%ld) : error: tag error - %s.\n", | 
|---|
| 523 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, kError::queryDescription(enmErrorCd)); | 
|---|
| 524 | if (phFile != NULL) | 
|---|
| 525 | fputc(*pCurFile->pszCurrent, phFile); /* if this proove to be very slow, we'll have to buffer writes better. */ | 
|---|
| 526 | pCurFile->pszCurrent++; | 
|---|
| 527 | ulRc += 0x00000001; | 
|---|
| 528 | } | 
|---|
| 529 | } | 
|---|
| 530 | else | 
|---|
| 531 | { | 
|---|
| 532 | fprintf(phLog, "%s(%ld) : error:  error occurred extracting tag.\n\tPossible reasons: unbalanced quotes, missing '>',...\n", | 
|---|
| 533 | pCurFile->getFilename(), pCurFile->getLineNumber()+1); | 
|---|
| 534 | if (phFile != NULL) | 
|---|
| 535 | fputc(*pCurFile->pszCurrent, phFile); /* if this proove to be very slow, we'll have to buffer writes better. */ | 
|---|
| 536 | pCurFile->pszCurrent++; | 
|---|
| 537 | ulRc += 0x00000001; | 
|---|
| 538 | } | 
|---|
| 539 |  | 
|---|
| 540 | } | 
|---|
| 541 | /*************/ | 
|---|
| 542 | /*************/ | 
|---|
| 543 | /*  VARIABLE */ | 
|---|
| 544 | /*************/ | 
|---|
| 545 | /*************/ | 
|---|
| 546 | else if (pCurFile->pszCurrent[0] == '$' && pCurFile->pszCurrent[1] == '(') | 
|---|
| 547 | { | 
|---|
| 548 | psz = pCurFile->pszCurrent + 2; | 
|---|
| 549 | while (*psz != ')' && *psz != '\0' && (psz - pCurFile->pszCurrent) < (int)(sizeof(szVariable)-1)) | 
|---|
| 550 | psz++; | 
|---|
| 551 | if (*psz == ')') | 
|---|
| 552 | { | 
|---|
| 553 | strncpy(&szVariable[0], pCurFile->pszCurrent+2, psz - pCurFile->pszCurrent-2); | 
|---|
| 554 | szVariable[psz - pCurFile->pszCurrent - 2] = '\0'; | 
|---|
| 555 |  | 
|---|
| 556 | pVariable = lifoSql.findSub(&szVariable[0]); | 
|---|
| 557 | if (pVariable == NULL) | 
|---|
| 558 | pVariable = lifoVar.find(&szVariable[0]); | 
|---|
| 559 |  | 
|---|
| 560 | if (pVariable != NULL) | 
|---|
| 561 | { | 
|---|
| 562 | /* write variable */ | 
|---|
| 563 | if (phFile != NULL) | 
|---|
| 564 | fwrite(pVariable->getValue(), strlen(pVariable->getValue()), 1, phFile); | 
|---|
| 565 | } | 
|---|
| 566 | else | 
|---|
| 567 | {   /* warning - complain, skip and continue */ | 
|---|
| 568 | fprintf(phLog, "%s(%ld) : warning: Variable '%s' not defined.\n", | 
|---|
| 569 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, &szVariable[0]); | 
|---|
| 570 | if (phFile != NULL) | 
|---|
| 571 | fwrite(pCurFile->pszCurrent, psz - pCurFile->pszCurrent + 1, 1, phFile); | 
|---|
| 572 | ulRc += 0x00010000; | 
|---|
| 573 | } | 
|---|
| 574 | pCurFile->pszCurrent = psz + 1; | 
|---|
| 575 | } | 
|---|
| 576 | else | 
|---|
| 577 | {   /* error - complain, skip and continue. */ | 
|---|
| 578 | fprintf(phLog, "%s(%ld) : error: Missing left parenthese on variable expression\n", | 
|---|
| 579 | pCurFile->getFilename(), pCurFile->getLineNumber()+1); | 
|---|
| 580 | if (phFile != NULL) | 
|---|
| 581 | fputc(*pCurFile->pszCurrent, phFile); /* if this proove to be very slow, we'll have to buffer writes better. */ | 
|---|
| 582 | pCurFile->pszCurrent++; | 
|---|
| 583 | ulRc += 0x00000001; | 
|---|
| 584 | } | 
|---|
| 585 | } | 
|---|
| 586 | else | 
|---|
| 587 | {   /* next */ | 
|---|
| 588 | if (phFile != NULL) | 
|---|
| 589 | fputc(*pCurFile->pszCurrent, phFile); /* if this proove to be very slow, we'll have to buffer writes better. */ | 
|---|
| 590 | pCurFile->pszCurrent++; | 
|---|
| 591 | } | 
|---|
| 592 | } | 
|---|
| 593 |  | 
|---|
| 594 |  | 
|---|
| 595 | /* resume processing of parent file */ | 
|---|
| 596 | kFileEntry *pFE = lifoFile.pop(); | 
|---|
| 597 | if (pFE != NULL) | 
|---|
| 598 | { | 
|---|
| 599 | assert(pFE == pCurFile->queryParent()); | 
|---|
| 600 | pFE->pszCurrent = pCurFile->queryParentPointer(); | 
|---|
| 601 | } | 
|---|
| 602 | lifoUsed.push(pCurFile); | 
|---|
| 603 | pCurFile = pFE; | 
|---|
| 604 | } | 
|---|
| 605 |  | 
|---|
| 606 | /* close file */ | 
|---|
| 607 | if (phFile != NULL) | 
|---|
| 608 | fclose(phFile); | 
|---|
| 609 |  | 
|---|
| 610 | return ulRc; | 
|---|
| 611 | } | 
|---|
| 612 |  | 
|---|
| 613 |  | 
|---|
| 614 | /** | 
|---|
| 615 | * Tag function - kSql. | 
|---|
| 616 | * @returns   low  word: number of errors | 
|---|
| 617 | *            high word: number of warnings | 
|---|
| 618 | * @remark    See TAG_PARAMETER_LIST for parameters. | 
|---|
| 619 | *            Use TAG_PARAMETERS when calling this function. | 
|---|
| 620 | */ | 
|---|
| 621 | static unsigned long tagkSql(TAG_PARAMETER_LIST) | 
|---|
| 622 | { | 
|---|
| 623 | unsigned long   ulRc = 0; | 
|---|
| 624 |  | 
|---|
| 625 | try | 
|---|
| 626 | { | 
|---|
| 627 | lifoSql.push(new kSqlEntry(tag, &pCurFile->pszCurrent[i], pCurFile)); | 
|---|
| 628 | pCurFile->pszCurrent += i; | 
|---|
| 629 | } | 
|---|
| 630 | catch (kError::enmErrors enmErrorCd) | 
|---|
| 631 | { | 
|---|
| 632 | fprintf(phLog, "%s(%ld) : error: kSql tag - %s (errorcode=%d)\n", | 
|---|
| 633 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, | 
|---|
| 634 | kError::queryDescription(enmErrorCd), enmErrorCd); | 
|---|
| 635 | /* fake entry */ | 
|---|
| 636 | if (enmErrorCd != kError::error_invalid_tag) | 
|---|
| 637 | lifoSql.push(new kSqlEntry()); | 
|---|
| 638 | TAG_PARAMETER_LIST_UNREF; | 
|---|
| 639 | } | 
|---|
| 640 |  | 
|---|
| 641 | return ulRc; | 
|---|
| 642 | } | 
|---|
| 643 |  | 
|---|
| 644 |  | 
|---|
| 645 | /** | 
|---|
| 646 | * Tag function - /kSql. | 
|---|
| 647 | * @returns   low  word: number of errors | 
|---|
| 648 | *            high word: number of warnings | 
|---|
| 649 | * @remark    See TAG_PARAMETER_LIST for parameters. | 
|---|
| 650 | *            Use TAG_PARAMETERS when calling this function. | 
|---|
| 651 | */ | 
|---|
| 652 | static unsigned long tagEndkSql(TAG_PARAMETER_LIST) | 
|---|
| 653 | { | 
|---|
| 654 | unsigned long  ulRc = 0; | 
|---|
| 655 | kSqlEntry      *pCurSql; | 
|---|
| 656 |  | 
|---|
| 657 | pCurSql = lifoSql.pop(); | 
|---|
| 658 | if (pCurSql != NULL) | 
|---|
| 659 | { | 
|---|
| 660 | if (!pCurSql->eof()) | 
|---|
| 661 | { | 
|---|
| 662 | if (pCurSql->fetch()) | 
|---|
| 663 | { | 
|---|
| 664 | if (pCurSql->queryFileEntry() != NULL) | 
|---|
| 665 | { | 
|---|
| 666 | /* three cases: current file, lifoFile or lifoUsed */ | 
|---|
| 667 | if (pCurSql->queryFileEntry() == pCurFile) | 
|---|
| 668 | {   /* 1. current file */ | 
|---|
| 669 | pCurFile->pszCurrent = pCurSql->queryBackTrackPos(); | 
|---|
| 670 | } | 
|---|
| 671 | else if (lifoFile.exists(pCurSql->queryFileEntry())) | 
|---|
| 672 | {   /* 2. lifoFile */ | 
|---|
| 673 | lifoFile.popPush(pCurSql->queryFileEntry(), lifoUsed); | 
|---|
| 674 | pCurFile = lifoFile.pop(); | 
|---|
| 675 | if (pCurFile != NULL) | 
|---|
| 676 | pCurFile->pszCurrent = pCurSql->queryBackTrackPos(); | 
|---|
| 677 | else | 
|---|
| 678 | { | 
|---|
| 679 | fprintf(phLog, "fatal internal error(%s, %ld, %s, %d): kSqlEntry - pCurFile == NULL\n", | 
|---|
| 680 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, __FILE__, __LINE__); | 
|---|
| 681 | return (unsigned long)~0; | 
|---|
| 682 | } | 
|---|
| 683 | } | 
|---|
| 684 | else if (lifoUsed.exists(pCurSql->queryFileEntry())) | 
|---|
| 685 | {   /* 3. lifoUsed */ | 
|---|
| 686 | lifoFile.popPush(NULL, lifoUsed); | 
|---|
| 687 | assert(lifoFile.isEmpty()); | 
|---|
| 688 | if (rebuildFileLIFO(lifoFile, lifoUsed, pCurSql->queryFileEntry())) | 
|---|
| 689 | { | 
|---|
| 690 | pCurFile = lifoFile.pop(); assert(pCurFile == pCurSql->queryFileEntry()); | 
|---|
| 691 | pCurFile->pszCurrent = pCurSql->queryBackTrackPos(); | 
|---|
| 692 | } | 
|---|
| 693 | else | 
|---|
| 694 | { | 
|---|
| 695 | fprintf(phLog, "fatal internal error(%s, %ld, %s, %d): rebuildLIFO failed\n", | 
|---|
| 696 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, __FILE__, __LINE__); | 
|---|
| 697 | return (unsigned long)~0; | 
|---|
| 698 | } | 
|---|
| 699 | } | 
|---|
| 700 | else | 
|---|
| 701 | { | 
|---|
| 702 | fprintf(phLog, "internal error(%s, %ld, %s, %d): pFileEntry == NULL\n", | 
|---|
| 703 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, __FILE__, __LINE__); | 
|---|
| 704 | pCurSql = lifoSql.pop(); /* neutralize the push below */ | 
|---|
| 705 | } | 
|---|
| 706 |  | 
|---|
| 707 | lifoSql.push(pCurSql); | 
|---|
| 708 | pCurSql = NULL; | 
|---|
| 709 | } | 
|---|
| 710 | else | 
|---|
| 711 | { | 
|---|
| 712 | fprintf(phLog, "internal error(%s, %ld, %s, %d): kSqlEntry - pFileEntry == NULL\n", | 
|---|
| 713 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, __FILE__, __LINE__); | 
|---|
| 714 | pCurFile->pszCurrent += i; | 
|---|
| 715 | } | 
|---|
| 716 | } | 
|---|
| 717 | else | 
|---|
| 718 | { | 
|---|
| 719 | fprintf(phLog, "%s(%ld) : error: sql error, %s\n", | 
|---|
| 720 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, | 
|---|
| 721 | pCurSql->querySqlLastError()); | 
|---|
| 722 | pCurFile->pszCurrent += i; | 
|---|
| 723 | } | 
|---|
| 724 | } | 
|---|
| 725 |  | 
|---|
| 726 | /* finished processing this tag? then delete it! */ | 
|---|
| 727 | if (pCurSql != NULL) | 
|---|
| 728 | { | 
|---|
| 729 | delete pCurSql; | 
|---|
| 730 | pCurFile->pszCurrent += i; | 
|---|
| 731 | } | 
|---|
| 732 | } | 
|---|
| 733 | else | 
|---|
| 734 | { | 
|---|
| 735 | fprintf(phLog, "%s(%ld) : error: unexpected '/kSql' tag.\n", | 
|---|
| 736 | pCurFile->getFilename(), pCurFile->getLineNumber()+1); | 
|---|
| 737 | pCurFile->pszCurrent += i; | 
|---|
| 738 | TAG_PARAMETER_LIST_UNREF; | 
|---|
| 739 | } | 
|---|
| 740 |  | 
|---|
| 741 | return ulRc; | 
|---|
| 742 | } | 
|---|
| 743 |  | 
|---|
| 744 |  | 
|---|
| 745 | /** | 
|---|
| 746 | * Tag function - kTemplate. | 
|---|
| 747 | * @returns   low  word: number of errors | 
|---|
| 748 | *            high word: number of warnings | 
|---|
| 749 | * @param     phFile    Reference to current output file. | 
|---|
| 750 | * @param     pOptions  Pointer to the options struct. | 
|---|
| 751 | * @remark    See TAG_PARAMETER_LIST for parameters. | 
|---|
| 752 | *            Use TAG_PARAMETERS when calling this function. | 
|---|
| 753 | */ | 
|---|
| 754 | static unsigned long tagkTemplate(TAG_PARAMETER_LIST, FILE * &phFile, const POPTIONS pOptions) | 
|---|
| 755 | { | 
|---|
| 756 | unsigned long    ulRc = 0; | 
|---|
| 757 | const char      *pszFilename; | 
|---|
| 758 |  | 
|---|
| 759 | /* verify parameters */ | 
|---|
| 760 | if (tag.getParameterCount() > 1 && tag.getParameterCount() == 0) | 
|---|
| 761 | { | 
|---|
| 762 | fprintf(phLog, "%s(%ld) : warning: kTemplate - incorrect number of parameters.\n", | 
|---|
| 763 | pCurFile->getFilename(), pCurFile->getLineNumber()+1); | 
|---|
| 764 | ulRc += 0x00010000; | 
|---|
| 765 | } | 
|---|
| 766 |  | 
|---|
| 767 | pszFilename = tag.queryParameter("filename"); | 
|---|
| 768 | if (pszFilename != NULL) | 
|---|
| 769 | { | 
|---|
| 770 | char  szFullFileName[CCHMAXPATH]; | 
|---|
| 771 | if (phFile != NULL) | 
|---|
| 772 | fclose(phFile); | 
|---|
| 773 | if (strlen(pszFilename) + strlen(pOptions->pszBaseDir) + 1 + 1 < sizeof(szFullFileName)) | 
|---|
| 774 | { | 
|---|
| 775 | sprintf(&szFullFileName[0], "%s\\%s", pOptions->pszBaseDir, pszFilename); | 
|---|
| 776 | phFile = fopen(&szFullFileName[0], "wb"); | 
|---|
| 777 | if (phFile != NULL) | 
|---|
| 778 | fprintf(phLog, "%s(%ld) : info: new output file, '%s'.\n", | 
|---|
| 779 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, &szFullFileName[0]); | 
|---|
| 780 | else | 
|---|
| 781 | { | 
|---|
| 782 | fprintf(phLog, "%s(%ld) : error: kTemplate - error opening output file '%s'.\n", | 
|---|
| 783 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, &szFullFileName[0]); | 
|---|
| 784 | ulRc += 0x00000001; | 
|---|
| 785 | } | 
|---|
| 786 | } | 
|---|
| 787 | else | 
|---|
| 788 | { | 
|---|
| 789 | fprintf(phLog, "%s(%ld) : error: kTemplate - filename and base dir is too long! '%s\\%s'.\n", | 
|---|
| 790 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, pOptions->pszBaseDir, pszFilename); | 
|---|
| 791 | ulRc += 0x00000001; | 
|---|
| 792 | } | 
|---|
| 793 | } | 
|---|
| 794 | else | 
|---|
| 795 | { | 
|---|
| 796 | fprintf(phLog, "%s(%ld) : error: kTemplate - filename is missing.\n", | 
|---|
| 797 | pCurFile->getFilename(), pCurFile->getLineNumber()+1); | 
|---|
| 798 | ulRc += 0x00000001; | 
|---|
| 799 | TAG_PARAMETER_LIST_UNREF; | 
|---|
| 800 | } | 
|---|
| 801 |  | 
|---|
| 802 | pCurFile->pszCurrent += i; | 
|---|
| 803 |  | 
|---|
| 804 | return ulRc; | 
|---|
| 805 | } | 
|---|
| 806 |  | 
|---|
| 807 |  | 
|---|
| 808 | /** | 
|---|
| 809 | * Tag function - kInclude. | 
|---|
| 810 | * @returns   low  word: number of errors | 
|---|
| 811 | *            high word: number of warnings | 
|---|
| 812 | * @remark    See TAG_PARAMETER_LIST for parameters. | 
|---|
| 813 | *            Use TAG_PARAMETERS when calling this function. | 
|---|
| 814 | */ | 
|---|
| 815 | static unsigned long tagkInclude(TAG_PARAMETER_LIST) | 
|---|
| 816 | { | 
|---|
| 817 | unsigned long ulRc = 0; | 
|---|
| 818 |  | 
|---|
| 819 | try | 
|---|
| 820 | { | 
|---|
| 821 | lifoFile.push(pCurFile); | 
|---|
| 822 | pCurFile = new kFileEntry(tag, pCurFile->pszCurrent+i, pCurFile); | 
|---|
| 823 | } | 
|---|
| 824 | catch (kError::enmErrors enmErrorCd) | 
|---|
| 825 | { | 
|---|
| 826 | fprintf(phLog, "%s(%ld) : error: kInclude - %s\n", | 
|---|
| 827 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, | 
|---|
| 828 | kError::queryDescription(enmErrorCd)); | 
|---|
| 829 | pCurFile = lifoFile.pop(); | 
|---|
| 830 | ulRc = 0x00000001; | 
|---|
| 831 | TAG_PARAMETER_LIST_UNREF; | 
|---|
| 832 | } | 
|---|
| 833 |  | 
|---|
| 834 | return ulRc; | 
|---|
| 835 | } | 
|---|
| 836 |  | 
|---|
| 837 |  | 
|---|
| 838 | /** | 
|---|
| 839 | * Tag function - kGraph. | 
|---|
| 840 | * @returns   low  word: number of errors | 
|---|
| 841 | *            high word: number of warnings | 
|---|
| 842 | * @remark    See TAG_PARAMETER_LIST for parameters. | 
|---|
| 843 | *            Use TAG_PARAMETERS when calling this function. | 
|---|
| 844 | */ | 
|---|
| 845 | static unsigned long tagkGraph(TAG_PARAMETER_LIST, const POPTIONS pOptions) | 
|---|
| 846 | { | 
|---|
| 847 | unsigned long ulRc = 0; | 
|---|
| 848 | /** | 
|---|
| 849 | * Tag description: | 
|---|
| 850 | * <!kGraph filename="graph.gif" type=<lines|...> [subtype=<normal|...>] | 
|---|
| 851 | *  data="sql x,y,color,legend from...." | 
|---|
| 852 | *  data="sql x,y,color,legend from...." | 
|---|
| 853 | *  data="sql x,y,color,legend from...." | 
|---|
| 854 | *  ... | 
|---|
| 855 | *  > | 
|---|
| 856 | * [] = optional | 
|---|
| 857 | */ | 
|---|
| 858 | try | 
|---|
| 859 | { | 
|---|
| 860 | kGraph graph(tag, pOptions->pszBaseDir); | 
|---|
| 861 | graph.showWarnings(phLog, pCurFile); | 
|---|
| 862 | graph.save(); | 
|---|
| 863 | } | 
|---|
| 864 | catch (kError::enmErrors emnErrorCd) | 
|---|
| 865 | { | 
|---|
| 866 | fprintf(phLog, "%s(%ld) : error: kGraph - %s.\n", | 
|---|
| 867 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, | 
|---|
| 868 | kError::queryDescription(emnErrorCd)); | 
|---|
| 869 | ulRc = 0x00000001; | 
|---|
| 870 | TAG_PARAMETER_LIST_UNREF; | 
|---|
| 871 | } | 
|---|
| 872 | pCurFile->pszCurrent += i; | 
|---|
| 873 |  | 
|---|
| 874 | return ulRc; | 
|---|
| 875 | } | 
|---|
| 876 |  | 
|---|
| 877 |  | 
|---|
| 878 | /** | 
|---|
| 879 | * Tag function - kDefine. | 
|---|
| 880 | * @returns   low  word: number of errors | 
|---|
| 881 | *            high word: number of warnings | 
|---|
| 882 | * @remark    See TAG_PARAMETER_LIST for parameters. | 
|---|
| 883 | *            Use TAG_PARAMETERS when calling this function. | 
|---|
| 884 | */ | 
|---|
| 885 | static unsigned long tagkDefine(TAG_PARAMETER_LIST) | 
|---|
| 886 | { | 
|---|
| 887 | unsigned long ulRc = 0; | 
|---|
| 888 |  | 
|---|
| 889 | fprintf(phLog, "%s(%ld) : error: kDefine - This tag is not implemented yet.\n", | 
|---|
| 890 | pCurFile->getFilename(), pCurFile->getLineNumber()+1); | 
|---|
| 891 | ulRc = 0x00000001; | 
|---|
| 892 | TAG_PARAMETER_LIST_UNREF; | 
|---|
| 893 |  | 
|---|
| 894 | return ulRc; | 
|---|
| 895 | } | 
|---|
| 896 |  | 
|---|
| 897 |  | 
|---|
| 898 | /** | 
|---|
| 899 | * Tag function - kUndef. | 
|---|
| 900 | * @returns   low  word: number of errors | 
|---|
| 901 | *            high word: number of warnings | 
|---|
| 902 | * @remark    See TAG_PARAMETER_LIST for parameters. | 
|---|
| 903 | *            Use TAG_PARAMETERS when calling this function. | 
|---|
| 904 | */ | 
|---|
| 905 | static unsigned long tagkUndef(TAG_PARAMETER_LIST) | 
|---|
| 906 | { | 
|---|
| 907 | unsigned long ulRc = 0; | 
|---|
| 908 |  | 
|---|
| 909 | fprintf(phLog, "%s(%ld) : error: kUndef - This tag is not implemented yet.\n", | 
|---|
| 910 | pCurFile->getFilename(), pCurFile->getLineNumber()+1); | 
|---|
| 911 | ulRc = 0x00000001; | 
|---|
| 912 | TAG_PARAMETER_LIST_UNREF; | 
|---|
| 913 |  | 
|---|
| 914 | return ulRc; | 
|---|
| 915 | } | 
|---|
| 916 |  | 
|---|
| 917 |  | 
|---|
| 918 | /** | 
|---|
| 919 | * Tag function - kIf. | 
|---|
| 920 | * @returns   low  word: number of errors | 
|---|
| 921 | *            high word: number of warnings | 
|---|
| 922 | * @remark    See TAG_PARAMETER_LIST for parameters. | 
|---|
| 923 | *            Use TAG_PARAMETERS when calling this function. | 
|---|
| 924 | */ | 
|---|
| 925 | static unsigned long tagkIf(TAG_PARAMETER_LIST) | 
|---|
| 926 | { | 
|---|
| 927 | unsigned long ulRc = 0; | 
|---|
| 928 |  | 
|---|
| 929 | fprintf(phLog, "%s(%ld) : error: kIf - This tag is not implemented yet.\n", | 
|---|
| 930 | pCurFile->getFilename(), pCurFile->getLineNumber()+1); | 
|---|
| 931 | ulRc = 0x00000001; | 
|---|
| 932 | TAG_PARAMETER_LIST_UNREF; | 
|---|
| 933 |  | 
|---|
| 934 | return ulRc; | 
|---|
| 935 | } | 
|---|
| 936 |  | 
|---|
| 937 |  | 
|---|
| 938 | /** | 
|---|
| 939 | * Tag function - kElse. | 
|---|
| 940 | * @returns   low  word: number of errors | 
|---|
| 941 | *            high word: number of warnings | 
|---|
| 942 | * @remark    See TAG_PARAMETER_LIST for parameters. | 
|---|
| 943 | *            Use TAG_PARAMETERS when calling this function. | 
|---|
| 944 | */ | 
|---|
| 945 | static unsigned long tagkElse(TAG_PARAMETER_LIST) | 
|---|
| 946 | { | 
|---|
| 947 | unsigned long ulRc = 0; | 
|---|
| 948 |  | 
|---|
| 949 | fprintf(phLog, "%s(%ld) : error: kElse - This tag is not implemented yet.\n", | 
|---|
| 950 | pCurFile->getFilename(), pCurFile->getLineNumber()+1); | 
|---|
| 951 | ulRc = 0x00000001; | 
|---|
| 952 | TAG_PARAMETER_LIST_UNREF; | 
|---|
| 953 |  | 
|---|
| 954 | return ulRc; | 
|---|
| 955 | } | 
|---|
| 956 |  | 
|---|
| 957 |  | 
|---|
| 958 | /** | 
|---|
| 959 | * Tag function - kEndif. | 
|---|
| 960 | * @returns   low  word: number of errors | 
|---|
| 961 | *            high word: number of warnings | 
|---|
| 962 | * @remark    See TAG_PARAMETER_LIST for parameters. | 
|---|
| 963 | *            Use TAG_PARAMETERS when calling this function. | 
|---|
| 964 | */ | 
|---|
| 965 | static unsigned long tagkEndif(TAG_PARAMETER_LIST) | 
|---|
| 966 | { | 
|---|
| 967 | unsigned long ulRc = 0; | 
|---|
| 968 |  | 
|---|
| 969 | fprintf(phLog, "%s(%ld) : error: kEndif - This tag is not implemented yet.\n", | 
|---|
| 970 | pCurFile->getFilename(), pCurFile->getLineNumber()+1); | 
|---|
| 971 | ulRc = 0x00000001; | 
|---|
| 972 | TAG_PARAMETER_LIST_UNREF; | 
|---|
| 973 |  | 
|---|
| 974 | return ulRc; | 
|---|
| 975 | } | 
|---|
| 976 |  | 
|---|
| 977 |  | 
|---|
| 978 | #if 0 | 
|---|
| 979 | /** | 
|---|
| 980 | * Tag function - k. | 
|---|
| 981 | * @returns   low  word: number of errors | 
|---|
| 982 | *            high word: number of warnings | 
|---|
| 983 | * @remark    See TAG_PARAMETER_LIST for parameters. | 
|---|
| 984 | *            Use TAG_PARAMETERS when calling this function. | 
|---|
| 985 | */ | 
|---|
| 986 | static unsigned long tagk(TAG_PARAMETER_LIST) | 
|---|
| 987 | { | 
|---|
| 988 | unsigned long ulRc = 0; | 
|---|
| 989 |  | 
|---|
| 990 | TAG_PARAMETER_LIST_UNREF; | 
|---|
| 991 |  | 
|---|
| 992 | return ulRc; | 
|---|
| 993 | } | 
|---|
| 994 | #endif | 
|---|
| 995 |  | 
|---|
| 996 |  | 
|---|
| 997 | /** | 
|---|
| 998 | * Rebuild a fileentry based on a given file entry. | 
|---|
| 999 | * @returns   success indicator. TRUE / FALSE. | 
|---|
| 1000 | * @param     lifoFile       Target. | 
|---|
| 1001 | * @param     lifoUsed       Source. | 
|---|
| 1002 | * @param     pFileEntryTop  New to file entry. | 
|---|
| 1003 | * @remark    Recusive. | 
|---|
| 1004 | */ | 
|---|
| 1005 | static BOOL rebuildFileLIFO(kLIFO<kFileEntry> &lifoFile, kLIFO<kFileEntry> &lifoUsed, const kFileEntry *pFileEntryTop) | 
|---|
| 1006 | { | 
|---|
| 1007 | /* base case */ | 
|---|
| 1008 | if (pFileEntryTop == NULL) | 
|---|
| 1009 | return TRUE; | 
|---|
| 1010 | /* general case */ | 
|---|
| 1011 | pFileEntryTop = lifoUsed.get(pFileEntryTop); | 
|---|
| 1012 | if (pFileEntryTop != NULL && rebuildFileLIFO(lifoFile, lifoUsed, pFileEntryTop->queryParent())) | 
|---|
| 1013 | lifoFile.push((kFileEntry*)pFileEntryTop); | 
|---|
| 1014 | else | 
|---|
| 1015 | return FALSE; | 
|---|
| 1016 | return TRUE; | 
|---|
| 1017 | } | 
|---|
| 1018 |  | 
|---|
| 1019 |  | 
|---|
| 1020 | /** | 
|---|
| 1021 | * Duplicates a string. | 
|---|
| 1022 | * @returns   Pointer to stringcopy. Remeber to delete this! | 
|---|
| 1023 | * @param     psz  Pointer to string to duplicate. | 
|---|
| 1024 | */ | 
|---|
| 1025 | static char *dupeString(const char *psz) | 
|---|
| 1026 | { | 
|---|
| 1027 | char *pszDupe; | 
|---|
| 1028 | if (psz == NULL) | 
|---|
| 1029 | return NULL; | 
|---|
| 1030 | pszDupe = new char[strlen(psz)+1]; | 
|---|
| 1031 | return strcpy(pszDupe, psz); | 
|---|
| 1032 | } | 
|---|
| 1033 |  | 
|---|
| 1034 |  | 
|---|
| 1035 | #if 0 // not used | 
|---|
| 1036 | /** | 
|---|
| 1037 | * Upcases a char. | 
|---|
| 1038 | * @returns   Upper case of the char given in ch. | 
|---|
| 1039 | * @param     ch  Char to capitalize. | 
|---|
| 1040 | */ | 
|---|
| 1041 | inline char upcase(char ch) | 
|---|
| 1042 | { | 
|---|
| 1043 | return ch >= 'a' && ch <= 'z' ? (char)(ch - ('a' - 'A')) : ch; | 
|---|
| 1044 | } | 
|---|
| 1045 |  | 
|---|
| 1046 |  | 
|---|
| 1047 | /** | 
|---|
| 1048 | * Searches for a substring in a string. | 
|---|
| 1049 | * @returns   Pointer to start of substring when found, NULL when not found. | 
|---|
| 1050 | * @param     pszStr     String to be searched. | 
|---|
| 1051 | * @param     pszSubStr  String to be searched. | 
|---|
| 1052 | * @remark    Depends on the upcase function. | 
|---|
| 1053 | */ | 
|---|
| 1054 | static char *stristr(const char *pszStr, const char *pszSubStr) | 
|---|
| 1055 | { | 
|---|
| 1056 | int cchSubStr = strlen(pszSubStr); | 
|---|
| 1057 | int i = 0; | 
|---|
| 1058 |  | 
|---|
| 1059 | while (*pszStr != '\0' && i < cchSubStr) | 
|---|
| 1060 | { | 
|---|
| 1061 | i = 0; | 
|---|
| 1062 | while (i < cchSubStr && pszStr[i] != '\0' && | 
|---|
| 1063 | (upcase(pszStr[i]) == upcase(pszSubStr[i]))) | 
|---|
| 1064 | i++; | 
|---|
| 1065 | pszStr++; | 
|---|
| 1066 | } | 
|---|
| 1067 |  | 
|---|
| 1068 | return (char*)(*pszStr != '\0' ? pszStr - 1 : NULL); | 
|---|
| 1069 | } | 
|---|
| 1070 |  | 
|---|
| 1071 |  | 
|---|
| 1072 | /** | 
|---|
| 1073 | * Trims a string, that is removing blank spaces at start and end. | 
|---|
| 1074 | * @returns   Pointer to first non-blank char. | 
|---|
| 1075 | * @param     psz  Pointer to string. | 
|---|
| 1076 | * @result    Blank at end of string is removed. ('\0' is moved to the left.) | 
|---|
| 1077 | */ | 
|---|
| 1078 | static char *trim(char *psz) | 
|---|
| 1079 | { | 
|---|
| 1080 | int i; | 
|---|
| 1081 | if (psz == NULL) | 
|---|
| 1082 | return NULL; | 
|---|
| 1083 | while (*psz == ' ') | 
|---|
| 1084 | psz++; | 
|---|
| 1085 | i = strlen(psz) - 1; | 
|---|
| 1086 | while (i >= 0 && psz[i] == ' ') | 
|---|
| 1087 | i--; | 
|---|
| 1088 | psz[i+1] = '\0'; | 
|---|
| 1089 | return psz; | 
|---|
| 1090 | } | 
|---|
| 1091 |  | 
|---|
| 1092 |  | 
|---|
| 1093 | /** | 
|---|
| 1094 | * Trims left side of a string; that is removing blank spaces at start. | 
|---|
| 1095 | * @returns   Pointer to first non-blank char. | 
|---|
| 1096 | * @param     psz  Pointer to string. | 
|---|
| 1097 | * @remark    non-const edtion. | 
|---|
| 1098 | */ | 
|---|
| 1099 | static char *ltrim(char *psz) | 
|---|
| 1100 | { | 
|---|
| 1101 | while (*psz == ' ') | 
|---|
| 1102 | psz++; | 
|---|
| 1103 | return psz; | 
|---|
| 1104 | } | 
|---|
| 1105 |  | 
|---|
| 1106 |  | 
|---|
| 1107 | /** | 
|---|
| 1108 | * Trims left side of a string; that is removing blank spaces. | 
|---|
| 1109 | * @returns   Pointer to first non-blank char. | 
|---|
| 1110 | * @param     psz  Pointer to string. | 
|---|
| 1111 | * @remark    const edtion. | 
|---|
| 1112 | */ | 
|---|
| 1113 | static const char *ltrim(const char *psz) | 
|---|
| 1114 | { | 
|---|
| 1115 | while (*psz == ' ') | 
|---|
| 1116 | psz++; | 
|---|
| 1117 | return psz; | 
|---|
| 1118 | } | 
|---|
| 1119 |  | 
|---|
| 1120 |  | 
|---|
| 1121 | /** | 
|---|
| 1122 | * Trims left side of a string; that is removing blank spaces, new lines and tabs. | 
|---|
| 1123 | * @returns   Pointer to first non-blank char. | 
|---|
| 1124 | * @param     psz  Pointer to string. | 
|---|
| 1125 | * @remark    non-const edtion. | 
|---|
| 1126 | */ | 
|---|
| 1127 | static char *ltrimL(char *psz) | 
|---|
| 1128 | { | 
|---|
| 1129 | while (*psz == ' ' || *psz == '\t' || *psz == '\r' || *psz == '\n') | 
|---|
| 1130 | psz++; | 
|---|
| 1131 | return psz; | 
|---|
| 1132 | } | 
|---|
| 1133 | #endif | 
|---|
| 1134 |  | 
|---|
| 1135 | /** | 
|---|
| 1136 | * Trims left side of a string; that is removing blank spaces, new lines and tabs. | 
|---|
| 1137 | * @returns   Pointer to first non-blank char. | 
|---|
| 1138 | * @param     psz  Pointer to string. | 
|---|
| 1139 | * @remark    const edtion. | 
|---|
| 1140 | */ | 
|---|
| 1141 | static const char *ltrimL(const char *psz) | 
|---|
| 1142 | { | 
|---|
| 1143 | while (*psz == ' ' || *psz == '\t' || *psz == '\r' || *psz == '\n') | 
|---|
| 1144 | psz++; | 
|---|
| 1145 | return psz; | 
|---|
| 1146 | } | 
|---|
| 1147 |  | 
|---|
| 1148 |  | 
|---|
| 1149 | /** | 
|---|
| 1150 | * Formats a raw message to a readable message. | 
|---|
| 1151 | * @returns   Pointer to a static data field containing the formatted message. | 
|---|
| 1152 | * @param     pszMsg  message to format. | 
|---|
| 1153 | */ | 
|---|
| 1154 | const char *kError::formatMessage(const char *pszMsg) | 
|---|
| 1155 | { | 
|---|
| 1156 | static char szData[256]; | 
|---|
| 1157 | int i = 0; | 
|---|
| 1158 |  | 
|---|
| 1159 | /* skip first word */ | 
|---|
| 1160 | while (*pszMsg != '_' && *pszMsg != '\0') | 
|---|
| 1161 | pszMsg++; | 
|---|
| 1162 | if (pszMsg != '\0') | 
|---|
| 1163 | { | 
|---|
| 1164 | pszMsg++; | 
|---|
| 1165 | do | 
|---|
| 1166 | { | 
|---|
| 1167 | if (*pszMsg == '_') | 
|---|
| 1168 | szData[i++] = ' '; | 
|---|
| 1169 | else | 
|---|
| 1170 | szData[i++] = *pszMsg; | 
|---|
| 1171 | } while (*pszMsg++ != '\0'); | 
|---|
| 1172 |  | 
|---|
| 1173 | strcat(&szData[0], "."); | 
|---|
| 1174 | } | 
|---|
| 1175 | else | 
|---|
| 1176 | szData[0] = '\0'; | 
|---|
| 1177 |  | 
|---|
| 1178 | return &szData[0]; | 
|---|
| 1179 | } | 
|---|
| 1180 |  | 
|---|
| 1181 |  | 
|---|
| 1182 | /** | 
|---|
| 1183 | * Give a description of an error code. | 
|---|
| 1184 | * @returns   "Read only"/const string. Never NULL. | 
|---|
| 1185 | * @param     emnError  Error code. | 
|---|
| 1186 | */ | 
|---|
| 1187 | const char *kError::queryDescription(kError::enmErrors enmError) | 
|---|
| 1188 | { | 
|---|
| 1189 | switch (enmError) | 
|---|
| 1190 | { | 
|---|
| 1191 | case error_sql_failed: | 
|---|
| 1192 | return kSqlEntry::querySqlLastError(); | 
|---|
| 1193 |  | 
|---|
| 1194 | ErrorDescCase(no_error                            ); | 
|---|
| 1195 | ErrorDescCase(error_unexpected_end_of_string                 ); | 
|---|
| 1196 | ErrorDescCase(error_unexpected_eot                           ); | 
|---|
| 1197 | ErrorDescCase(error_invalid_tag_start_char                   ); | 
|---|
| 1198 | ErrorDescCase(error_invalid_tagname                          ); | 
|---|
| 1199 | ErrorDescCase(error_invalid_tag                              ); | 
|---|
| 1200 | ErrorDescCase(error_no_filename                              ); | 
|---|
| 1201 | ErrorDescCase(error_unexpected_eof                           ); | 
|---|
| 1202 | ErrorDescCase(error_unbalanced_quotes                        ); | 
|---|
| 1203 | ErrorDescCase(error_eot_not_found                            ); | 
|---|
| 1204 | ErrorDescCase(error_opening_file                             ); | 
|---|
| 1205 | ErrorDescCase(error_determing_file_size                      ); | 
|---|
| 1206 | ErrorDescCase(error_new_failed                               ); | 
|---|
| 1207 | ErrorDescCase(error_reading_file                             ); | 
|---|
| 1208 | ErrorDescCase(error_incorrect_number_of_parameters           ); | 
|---|
| 1209 | ErrorDescCase(error_missing_sql                              ); | 
|---|
| 1210 | ErrorDescCase(error_invalid_sql_tag                          ); | 
|---|
| 1211 | ErrorDescCase(error_opening_output_file                      ); | 
|---|
| 1212 | ErrorDescCase(error_graph_to_small                           ); | 
|---|
| 1213 | ErrorDescCase(error_graph_type_must_be_specified_before_data ); | 
|---|
| 1214 | ErrorDescCase(error_data_param_is_missing_value              ); | 
|---|
| 1215 | ErrorDescCase(error_type_param_is_missing_value              ); | 
|---|
| 1216 | ErrorDescCase(error_invalid_type                             ); | 
|---|
| 1217 | ErrorDescCase(error_filename_param_is_missing_value          ); | 
|---|
| 1218 | ErrorDescCase(error_width_cx_param_is_missing_value          ); | 
|---|
| 1219 | ErrorDescCase(error_height_cy_param_is_missing_value         ); | 
|---|
| 1220 | ErrorDescCase(error_graph_type_is_missing                    ); | 
|---|
| 1221 | ErrorDescCase(error_graph_subtype_is_invalid                 ); | 
|---|
| 1222 | ErrorDescCase(error_filename_is_missing                      ); | 
|---|
| 1223 | ErrorDescCase(error_no_data                                  ); | 
|---|
| 1224 | ErrorDescCase(error_invalid_dimentions                       ); | 
|---|
| 1225 | ErrorDescCase(error_data_param_is_missing_sql_statement      ); | 
|---|
| 1226 | ErrorDescCase(error_xstart_param_is_missing_value            ); | 
|---|
| 1227 | ErrorDescCase(error_xend_param_is_missing_value              ); | 
|---|
| 1228 | ErrorDescCase(error_ystart_param_is_missing_value            ); | 
|---|
| 1229 | ErrorDescCase(error_yend_param_is_missing_value              ); | 
|---|
| 1230 |  | 
|---|
| 1231 | ErrorDescCase(warning_illegal_string_char                    ); | 
|---|
| 1232 | ErrorDescCase(warning_too_many_parameters                    ); | 
|---|
| 1233 | ErrorDescCase(warning_unexpected_end_of_string               ); | 
|---|
| 1234 | ErrorDescCase(warning_unexpected_eot                         ); | 
|---|
| 1235 | ErrorDescCase(warning_failed_to_open_background_image        ); | 
|---|
| 1236 | ErrorDescCase(warning_failed_to_load_background_image        ); | 
|---|
| 1237 | ErrorDescCase(warning_invalid_sub_type                       ); | 
|---|
| 1238 | ErrorDescCase(warning_title_param_is_missing_value           ); | 
|---|
| 1239 | ErrorDescCase(warning_titlex_param_is_missing_value          ); | 
|---|
| 1240 | ErrorDescCase(warning_titley_param_is_missing_value          ); | 
|---|
| 1241 | ErrorDescCase(warning_invalid_parameter                      ); | 
|---|
| 1242 | ErrorDescCase(warning_legend_is_not_implemented_yet          ); | 
|---|
| 1243 | ErrorDescCase(warning_failed_to_convert_date                 ); | 
|---|
| 1244 | ErrorDescCase(warning_invalid_color_value                    ); | 
|---|
| 1245 | ErrorDescCase(warning_to_many_fields_in_data_sql             ); | 
|---|
| 1246 | ErrorDescCase(warning_pie_not_implemented_yet                ); | 
|---|
| 1247 | ErrorDescCase(warning_negative_values_are_not_supported_yet  ); | 
|---|
| 1248 | ErrorDescCase(warning_background_param_is_missing_value      ); | 
|---|
| 1249 | ErrorDescCase(warning_backgroundcolor_is_invalid             ); | 
|---|
| 1250 | ErrorDescCase(warning_backgroundcolor_param_is_missing_value ); | 
|---|
| 1251 | ErrorDescCase(warning_foregroundcolor_is_invalid             ); | 
|---|
| 1252 | ErrorDescCase(warning_foregroundcolor_param_is_missing_value ); | 
|---|
| 1253 | ErrorDescCase(warning_axiscolor_is_invalid                   ); | 
|---|
| 1254 | ErrorDescCase(warning_axiscolor_param_is_missing_value       ); | 
|---|
| 1255 | } | 
|---|
| 1256 | return "unknown error"; | 
|---|
| 1257 | } | 
|---|
| 1258 |  | 
|---|
| 1259 |  | 
|---|
| 1260 | /** | 
|---|
| 1261 | * Query for a warning. | 
|---|
| 1262 | * @returns   Const pointer to warning description. NULL if no warning. | 
|---|
| 1263 | */ | 
|---|
| 1264 | const char *kTag::queryWarning(void) | 
|---|
| 1265 | { | 
|---|
| 1266 | return enmWarning != kError::no_error ? kError::queryDescription(enmWarning) : NULL; | 
|---|
| 1267 | } | 
|---|
| 1268 |  | 
|---|
| 1269 |  | 
|---|
| 1270 | /** | 
|---|
| 1271 | * Anayses an tag: get tagname and parameters (if any). | 
|---|
| 1272 | * @param     pszTag  Pointer to tag buffer. | 
|---|
| 1273 | * @sketch | 
|---|
| 1274 | * @remark    Throws kError::emnErrors on error. | 
|---|
| 1275 | */ | 
|---|
| 1276 | void kTag::analyseTag(const char *pszTag) throw(kError::enmErrors) | 
|---|
| 1277 | { | 
|---|
| 1278 | char *psz = &szTag[0]; | 
|---|
| 1279 |  | 
|---|
| 1280 | /* skip blanks at start */ | 
|---|
| 1281 | while (*pszTag == ' ') | 
|---|
| 1282 | pszTag++; | 
|---|
| 1283 |  | 
|---|
| 1284 | /* tagname */ | 
|---|
| 1285 | if (*pszTag++ != '<') | 
|---|
| 1286 | throw(kError::error_invalid_tag_start_char); | 
|---|
| 1287 | pszTag = copyTag(psz, pszTag); | 
|---|
| 1288 | pszTagname = psz; | 
|---|
| 1289 | psz += strlen(psz) + 1; | 
|---|
| 1290 |  | 
|---|
| 1291 | /* parameters */ | 
|---|
| 1292 | if (strncmp(pszTagname, "!--", 3) != 0) /* ignore comments */ | 
|---|
| 1293 | { | 
|---|
| 1294 | try | 
|---|
| 1295 | { | 
|---|
| 1296 | pszTag = ltrimL(pszTag); | 
|---|
| 1297 | while (*pszTag != '>' && *pszTag != '\0' && cParameters < TAG_MAX_PARAMETERS) | 
|---|
| 1298 | { | 
|---|
| 1299 | /* parametername */ | 
|---|
| 1300 | pszTag = copyParameterName(psz, pszTag); | 
|---|
| 1301 | apszParameters[cParameters] = psz; | 
|---|
| 1302 | psz += strlen(psz) + 1; | 
|---|
| 1303 |  | 
|---|
| 1304 | /* parametervalue */ | 
|---|
| 1305 | apszValues[cParameters] = NULL; | 
|---|
| 1306 | pszTag = ltrimL(pszTag); | 
|---|
| 1307 | if (*pszTag == '=') | 
|---|
| 1308 | { | 
|---|
| 1309 | pszTag = ltrimL(pszTag + 1); | 
|---|
| 1310 | if (*pszTag != '\"') | 
|---|
| 1311 | pszTag = copyParameterValue1(psz, pszTag); | 
|---|
| 1312 | else | 
|---|
| 1313 | pszTag = copyParameterValue2(psz, pszTag); | 
|---|
| 1314 | apszValues[cParameters] = psz; | 
|---|
| 1315 | psz += strlen(psz) + 1; | 
|---|
| 1316 | } | 
|---|
| 1317 |  | 
|---|
| 1318 | /* parameter finished - next */ | 
|---|
| 1319 | cParameters++; | 
|---|
| 1320 | pszTag = ltrimL(pszTag); | 
|---|
| 1321 | } | 
|---|
| 1322 |  | 
|---|
| 1323 | /* check for warnings */ | 
|---|
| 1324 | if (*pszTag != '>' && cParameters >= TAG_MAX_PARAMETERS) | 
|---|
| 1325 | throw(kError::warning_too_many_parameters); | 
|---|
| 1326 | if (*pszTag != '>') | 
|---|
| 1327 | throw(kError::warning_unexpected_eot); | 
|---|
| 1328 | } | 
|---|
| 1329 | catch (kError::enmErrors enmErrorCd) | 
|---|
| 1330 | { | 
|---|
| 1331 | /* no fatal error --> warning */ | 
|---|
| 1332 | enmWarning = enmErrorCd; | 
|---|
| 1333 | } | 
|---|
| 1334 | } | 
|---|
| 1335 | } | 
|---|
| 1336 |  | 
|---|
| 1337 |  | 
|---|
| 1338 | /** | 
|---|
| 1339 | * Copy a tagname. | 
|---|
| 1340 | * @returns   Pointer to first char after the tag. (pszFrom) | 
|---|
| 1341 | * @param     pszTo    Pointer to target. | 
|---|
| 1342 | * @param     pszFrom  Pointer to value string. | 
|---|
| 1343 | * @remark    Throws kError::emnErrors on error, fatal for this object. | 
|---|
| 1344 | */ | 
|---|
| 1345 | const char *kTag::copyTag(char *pszTo, const char *pszFrom) throw(kError::enmErrors) | 
|---|
| 1346 | { | 
|---|
| 1347 | const char *psz = pszTo; | 
|---|
| 1348 |  | 
|---|
| 1349 | /* checks for errors */ | 
|---|
| 1350 | if (*pszFrom == '>') | 
|---|
| 1351 | throw(kError::error_unexpected_eot); | 
|---|
| 1352 |  | 
|---|
| 1353 | /* skip to start of tagname */ | 
|---|
| 1354 | while (*pszFrom == ' ') | 
|---|
| 1355 | pszFrom++; | 
|---|
| 1356 |  | 
|---|
| 1357 | /* copy string */ | 
|---|
| 1358 | while ( | 
|---|
| 1359 | (*pszFrom >= 'a' && *pszFrom <= 'z') || | 
|---|
| 1360 | (*pszFrom >= 'A' && *pszFrom <= 'Z') || | 
|---|
| 1361 | (*pszFrom >= '0' && *pszFrom <= '9') || | 
|---|
| 1362 | *pszFrom  == '/' || | 
|---|
| 1363 | *pszFrom  == '!' || *pszFrom == '-' //<!--> and <!k...> | 
|---|
| 1364 | ) | 
|---|
| 1365 | *pszTo++ = *pszFrom++; | 
|---|
| 1366 | *pszTo = '\0'; | 
|---|
| 1367 |  | 
|---|
| 1368 | /* checks for errors */ | 
|---|
| 1369 | if (*pszFrom == '\0') | 
|---|
| 1370 | throw(kError::error_unexpected_eot); | 
|---|
| 1371 | if (*pszFrom != '>' && *pszFrom != ' ' && strncmp("!--", psz, 3) != 0) //<!--aasdfv--> | 
|---|
| 1372 | throw(kError::error_invalid_tagname); | 
|---|
| 1373 |  | 
|---|
| 1374 | return pszFrom; | 
|---|
| 1375 | } | 
|---|
| 1376 |  | 
|---|
| 1377 |  | 
|---|
| 1378 | /** | 
|---|
| 1379 | * Copy a | 
|---|
| 1380 | * @returns   Pointer to first char after the tag. (pszFrom) | 
|---|
| 1381 | * @param     pszTo    Pointer to target. | 
|---|
| 1382 | * @param     pszFrom  Pointer to value string. | 
|---|
| 1383 | * @remark    Throws kError::emnErrors on error, fatal for this object. | 
|---|
| 1384 | */ | 
|---|
| 1385 | const char *kTag::copyParameterName(char *pszTo, const char *pszFrom) throw(kError::enmErrors) | 
|---|
| 1386 | { | 
|---|
| 1387 | /* checks for errors */ | 
|---|
| 1388 | if (*pszFrom == '>') | 
|---|
| 1389 | throw(kError::warning_unexpected_eot); | 
|---|
| 1390 |  | 
|---|
| 1391 | /* skip to start of parameter name */ | 
|---|
| 1392 | while (*pszFrom == ' ') | 
|---|
| 1393 | pszFrom++; | 
|---|
| 1394 |  | 
|---|
| 1395 | /* copy string */ | 
|---|
| 1396 | while ( | 
|---|
| 1397 | (*pszFrom >= 'a' && *pszFrom <= 'z') || | 
|---|
| 1398 | (*pszFrom >= 'A' && *pszFrom <= 'Z') || | 
|---|
| 1399 | (*pszFrom >= '0' && *pszFrom <= '9') | 
|---|
| 1400 | ) | 
|---|
| 1401 | *pszTo++ = *pszFrom++; | 
|---|
| 1402 | *pszTo = '\0'; | 
|---|
| 1403 |  | 
|---|
| 1404 | /* checks for errors */ | 
|---|
| 1405 | if (*pszFrom == '\0') | 
|---|
| 1406 | throw(kError::warning_unexpected_eot); | 
|---|
| 1407 |  | 
|---|
| 1408 | return pszFrom; | 
|---|
| 1409 | } | 
|---|
| 1410 |  | 
|---|
| 1411 |  | 
|---|
| 1412 | /** | 
|---|
| 1413 | * Copy a simple parameter value. A simple parameter value is not enclosed in "". | 
|---|
| 1414 | * @returns   Pointer to first char after the value. (pszFrom) | 
|---|
| 1415 | * @param     pszTo    Pointer to target. | 
|---|
| 1416 | * @param     pszFrom  Pointer to value string. | 
|---|
| 1417 | * @remark    Throws kError::emnErrors on warning, do not continue analysis. | 
|---|
| 1418 | */ | 
|---|
| 1419 | const char *kTag::copyParameterValue1(char *pszTo, const char *pszFrom) throw(kError::enmErrors) | 
|---|
| 1420 | { | 
|---|
| 1421 | /* skip to start of parameter value */ | 
|---|
| 1422 | while (*pszFrom == ' ') | 
|---|
| 1423 | pszFrom++; | 
|---|
| 1424 |  | 
|---|
| 1425 | /* copy string */ | 
|---|
| 1426 | while ( | 
|---|
| 1427 | (*pszFrom >= 'a' && *pszFrom <= 'z') || | 
|---|
| 1428 | (*pszFrom >= 'A' && *pszFrom <= 'Z') || | 
|---|
| 1429 | (*pszFrom >= '0' && *pszFrom <= '9') || | 
|---|
| 1430 | *pszFrom  == '.' || *pszFrom == ',' | 
|---|
| 1431 | ) | 
|---|
| 1432 | *pszTo++ = *pszFrom++; | 
|---|
| 1433 | *pszTo = '\0'; | 
|---|
| 1434 |  | 
|---|
| 1435 | /* check for warnings */ | 
|---|
| 1436 | if (*pszFrom == '\0') | 
|---|
| 1437 | throw(kError::warning_unexpected_eot); | 
|---|
| 1438 | if (*pszFrom !=  ' ' && *pszFrom != '>' && *pszFrom != '\n' && *pszFrom != '\r') | 
|---|
| 1439 | throw(kError::warning_illegal_string_char); | 
|---|
| 1440 |  | 
|---|
| 1441 | return pszFrom; | 
|---|
| 1442 | } | 
|---|
| 1443 |  | 
|---|
| 1444 |  | 
|---|
| 1445 | /** | 
|---|
| 1446 | * Copy an enclosed parameter value. Enclosed in "". | 
|---|
| 1447 | * @returns   Pointer to first char after the value. (pszFrom) | 
|---|
| 1448 | * @param     pszTo    Pointer to target. | 
|---|
| 1449 | * @param     pszFrom  Pointer to value string. | 
|---|
| 1450 | * @remark    Throws kError::emnErrors on warning, do not continue analysis. | 
|---|
| 1451 | */ | 
|---|
| 1452 | const char *kTag::copyParameterValue2(char *pszTo, const char *pszFrom) throw(kError::enmErrors) | 
|---|
| 1453 | { | 
|---|
| 1454 | /* skip to start " */ | 
|---|
| 1455 | while (*pszFrom != '\"' && *pszFrom != '>' && *pszFrom != '\0') | 
|---|
| 1456 | pszFrom++; | 
|---|
| 1457 | if (*pszFrom != '\"') | 
|---|
| 1458 | throw(kError::error_unexpected_end_of_string); | 
|---|
| 1459 | pszFrom++; | 
|---|
| 1460 |  | 
|---|
| 1461 | /* copy string */ | 
|---|
| 1462 | while (*pszFrom != '\"' /*&& *pszFrom != '>'*/ && *pszFrom != '\0') | 
|---|
| 1463 | *pszTo++ = *pszFrom++; | 
|---|
| 1464 | *pszTo = '\0'; | 
|---|
| 1465 |  | 
|---|
| 1466 | /* check for warnings */ | 
|---|
| 1467 | if (*pszFrom != '\"') | 
|---|
| 1468 | throw(kError::warning_unexpected_end_of_string); | 
|---|
| 1469 |  | 
|---|
| 1470 | return pszFrom + 1; | 
|---|
| 1471 | } | 
|---|
| 1472 |  | 
|---|
| 1473 |  | 
|---|
| 1474 | /** | 
|---|
| 1475 | * Is this the correct tag? | 
|---|
| 1476 | * @returns   TRUE pszTagname matches this->pszTagname, else FALSE. | 
|---|
| 1477 | * @param     pszTagname  Name to match. | 
|---|
| 1478 | */ | 
|---|
| 1479 | BOOL kTag::isTag(const char *pszTagname) const | 
|---|
| 1480 | { | 
|---|
| 1481 | if (pszTagname == NULL) | 
|---|
| 1482 | return FALSE; | 
|---|
| 1483 | return stricmp(pszTagname, this->pszTagname) == 0; | 
|---|
| 1484 | } | 
|---|
| 1485 |  | 
|---|
| 1486 |  | 
|---|
| 1487 | /** | 
|---|
| 1488 | * Constructor. | 
|---|
| 1489 | * @param     pszTag  Pointer to tag to analyse. | 
|---|
| 1490 | * @remark    Throws kError::emnErrors on warning, do not continue analysis. | 
|---|
| 1491 | */ | 
|---|
| 1492 | kTag::kTag(const char *pszTag) throw(kError::enmErrors) | 
|---|
| 1493 | : pszTagname(NULL), cParameters(0), enmWarning(kError::no_error) | 
|---|
| 1494 | { | 
|---|
| 1495 | analyseTag(pszTag); | 
|---|
| 1496 | } | 
|---|
| 1497 |  | 
|---|
| 1498 |  | 
|---|
| 1499 | /** | 
|---|
| 1500 | * Destructor. | 
|---|
| 1501 | */ | 
|---|
| 1502 | kTag::~kTag(void) | 
|---|
| 1503 | { | 
|---|
| 1504 | } | 
|---|
| 1505 |  | 
|---|
| 1506 |  | 
|---|
| 1507 | /** | 
|---|
| 1508 | * Gets the tag name. | 
|---|
| 1509 | * @returns   Const pointer to tag name. Not NULL. | 
|---|
| 1510 | */ | 
|---|
| 1511 | const char *kTag::getTagname(void) const | 
|---|
| 1512 | { | 
|---|
| 1513 | return pszTagname; | 
|---|
| 1514 | } | 
|---|
| 1515 |  | 
|---|
| 1516 |  | 
|---|
| 1517 | /** | 
|---|
| 1518 | * Gets the number of parameters found for this tag. | 
|---|
| 1519 | * @returns   Number of parameters. -1 on error (should never occur!). | 
|---|
| 1520 | */ | 
|---|
| 1521 | unsigned long kTag::getParameterCount(void) const | 
|---|
| 1522 | { | 
|---|
| 1523 | return cParameters; | 
|---|
| 1524 | } | 
|---|
| 1525 |  | 
|---|
| 1526 |  | 
|---|
| 1527 | /** | 
|---|
| 1528 | * Seek for the value of a given parameter. | 
|---|
| 1529 | * @returns   "Readonly"/const pointer to value. NULL if no value or parameter not found. | 
|---|
| 1530 | * @param     pszParameter  Pointer to parameter name. | 
|---|
| 1531 | * @remark    Parameters are case insensitive! | 
|---|
| 1532 | */ | 
|---|
| 1533 | const char *kTag::queryParameter(const char *pszParameter) const | 
|---|
| 1534 | { | 
|---|
| 1535 | unsigned int i = 0; | 
|---|
| 1536 | while (i < cParameters && stricmp(apszParameters[i], pszParameter) != 0) | 
|---|
| 1537 | i++; | 
|---|
| 1538 | return i < cParameters ? apszValues[i]: NULL; | 
|---|
| 1539 | } | 
|---|
| 1540 |  | 
|---|
| 1541 |  | 
|---|
| 1542 | /** | 
|---|
| 1543 | * Checks if a parameter exists. | 
|---|
| 1544 | * @returns   TRUE: exists, FALSE: does not exist. | 
|---|
| 1545 | * @param     pszParameter  Pointer to parameter name. | 
|---|
| 1546 | * @remark    Parameters are case insensitive! | 
|---|
| 1547 | */ | 
|---|
| 1548 | BOOL kTag::queryExists(const char *pszParameter) const | 
|---|
| 1549 | { | 
|---|
| 1550 | unsigned int i = 0; | 
|---|
| 1551 | while (i < cParameters && stricmp(apszParameters[i], pszParameter) != 0) | 
|---|
| 1552 | i++; | 
|---|
| 1553 | return i < cParameters; | 
|---|
| 1554 | } | 
|---|
| 1555 |  | 
|---|
| 1556 |  | 
|---|
| 1557 | /** | 
|---|
| 1558 | * Gets the parameter name for the given parameter number. | 
|---|
| 1559 | * @returns   Pointer to "readonly"/const parametername. NULL if outof range. | 
|---|
| 1560 | * @param     ulOrdinal  Parameter number. 0-based. | 
|---|
| 1561 | */ | 
|---|
| 1562 | const char *kTag::queryParameterName(unsigned long ulOrdinal) const | 
|---|
| 1563 | { | 
|---|
| 1564 | return ulOrdinal < cParameters ? apszParameters[ulOrdinal] : NULL; | 
|---|
| 1565 | } | 
|---|
| 1566 |  | 
|---|
| 1567 |  | 
|---|
| 1568 | /** | 
|---|
| 1569 | * Gets the value for the given parameter number. | 
|---|
| 1570 | * @returns   Pointer to "readonly"/const parameter value. NULL if outof range or no value. | 
|---|
| 1571 | * @param     ulOrdinal  Parameter number. 0-based. | 
|---|
| 1572 | * @remark    Return value NULL doesn't have to be an error, the parameter may not have a value! | 
|---|
| 1573 | */ | 
|---|
| 1574 | const char *kTag::queryParameterValue(unsigned long ulOrdinal) const | 
|---|
| 1575 | { | 
|---|
| 1576 | return ulOrdinal < cParameters ? apszValues[ulOrdinal] : NULL; | 
|---|
| 1577 | } | 
|---|
| 1578 |  | 
|---|
| 1579 |  | 
|---|
| 1580 | /** | 
|---|
| 1581 | * Opens and reads a file into memory. | 
|---|
| 1582 | * @param     pszFilename  Pointer to input filename. | 
|---|
| 1583 | * @remark    throws error code (enum). | 
|---|
| 1584 | */ | 
|---|
| 1585 | void kFileEntry::openAndReadFile(const char *pszFilename) throw (kError::enmErrors) | 
|---|
| 1586 | { | 
|---|
| 1587 | FILE *phFile; | 
|---|
| 1588 |  | 
|---|
| 1589 | phFile = fopen(pszFilename, "rb"); | 
|---|
| 1590 | if (phFile == NULL) | 
|---|
| 1591 | throw(kError::error_opening_file); | 
|---|
| 1592 | if (fseek(phFile, 0, SEEK_END) == 0 && | 
|---|
| 1593 | (cbFile = ftell(phFile)) != 0 && | 
|---|
| 1594 | fseek(phFile, 0, SEEK_SET) == 0 | 
|---|
| 1595 | ) | 
|---|
| 1596 | { | 
|---|
| 1597 | pszFile = new char[cbFile+1]; | 
|---|
| 1598 | if (pszFile != NULL) | 
|---|
| 1599 | { | 
|---|
| 1600 | memset(pszFile, 0, (size_t)(cbFile+1)); | 
|---|
| 1601 | if (fread(pszFile, cbFile, 1, phFile) != 1) | 
|---|
| 1602 | { | 
|---|
| 1603 | fclose(phFile); | 
|---|
| 1604 | throw(kError::error_reading_file); | 
|---|
| 1605 | } | 
|---|
| 1606 | fclose(phFile); | 
|---|
| 1607 | } | 
|---|
| 1608 | else | 
|---|
| 1609 | { | 
|---|
| 1610 | fclose(phFile); | 
|---|
| 1611 | throw(kError::error_new_failed); | 
|---|
| 1612 | } | 
|---|
| 1613 | } | 
|---|
| 1614 | else | 
|---|
| 1615 | { | 
|---|
| 1616 | fclose(phFile); | 
|---|
| 1617 | throw(kError::error_determing_file_size); | 
|---|
| 1618 | } | 
|---|
| 1619 | } | 
|---|
| 1620 |  | 
|---|
| 1621 |  | 
|---|
| 1622 | /** | 
|---|
| 1623 | * Creates a file entry object. | 
|---|
| 1624 | * @param     pszFilename  Pointer input filename. | 
|---|
| 1625 | * @sketch    Open file. | 
|---|
| 1626 | *            Find file length. | 
|---|
| 1627 | *            Read file into memory. | 
|---|
| 1628 | * @remark    throws error code enum. | 
|---|
| 1629 | */ | 
|---|
| 1630 | kFileEntry::kFileEntry(const char *pszFilename) throw (kError::enmErrors) : pParent(NULL), pszParent(NULL) | 
|---|
| 1631 | { | 
|---|
| 1632 | openAndReadFile(pszFilename); | 
|---|
| 1633 | strcpy(&szFilename[0], pszFilename); | 
|---|
| 1634 | pszCurrent = pszFile; | 
|---|
| 1635 | } | 
|---|
| 1636 |  | 
|---|
| 1637 |  | 
|---|
| 1638 | /** | 
|---|
| 1639 | * Create a file entry object with parent from a include statement. | 
|---|
| 1640 | * @parma     tag          Reference to tag object. | 
|---|
| 1641 | * @param     pszParent    Current pointer in parent file. | 
|---|
| 1642 | * @param     pParent      Pointer to current file entry. | 
|---|
| 1643 | * @sketch    Open and read file into memory. | 
|---|
| 1644 | *            Copy filename. | 
|---|
| 1645 | *            Set current pointer. | 
|---|
| 1646 | * @remark    throws error code enum. | 
|---|
| 1647 | *            TODO - use not fully implemented. | 
|---|
| 1648 | */ | 
|---|
| 1649 | kFileEntry::kFileEntry(const kTag &tag, const char *pszParent, const kFileEntry *pParent) throw (kError::enmErrors) | 
|---|
| 1650 | : pParent(pParent), pszParent(pszParent) | 
|---|
| 1651 | { | 
|---|
| 1652 | const char *pszFilename; | 
|---|
| 1653 |  | 
|---|
| 1654 | /* verify tag */ | 
|---|
| 1655 | if (stricmp(tag.getTagname(), "!kInclude")) | 
|---|
| 1656 | throw(kError::error_invalid_tag); | 
|---|
| 1657 |  | 
|---|
| 1658 | /* verify parameters */ | 
|---|
| 1659 | if (tag.getParameterCount() != 1) | 
|---|
| 1660 | throw(kError::error_incorrect_number_of_parameters); | 
|---|
| 1661 |  | 
|---|
| 1662 | /* get filename */ | 
|---|
| 1663 | pszFilename = tag.queryParameter("filename"); | 
|---|
| 1664 | if (pszFilename == NULL) | 
|---|
| 1665 | throw(kError::error_no_filename); | 
|---|
| 1666 |  | 
|---|
| 1667 | /* copy filename */ | 
|---|
| 1668 | strcpy(&szFilename[0], pszFilename); | 
|---|
| 1669 |  | 
|---|
| 1670 | /* open and read file */ | 
|---|
| 1671 | openAndReadFile(&szFilename[0]); | 
|---|
| 1672 | pszCurrent = pszFile; | 
|---|
| 1673 | } | 
|---|
| 1674 |  | 
|---|
| 1675 |  | 
|---|
| 1676 | /** | 
|---|
| 1677 | * Destroys the file entry object. | 
|---|
| 1678 | */ | 
|---|
| 1679 | kFileEntry::~kFileEntry() | 
|---|
| 1680 | { | 
|---|
| 1681 | delete pszFile; | 
|---|
| 1682 | pszCurrent = NULL; | 
|---|
| 1683 |  | 
|---|
| 1684 | } | 
|---|
| 1685 |  | 
|---|
| 1686 |  | 
|---|
| 1687 | /** | 
|---|
| 1688 | * Get linenumber. | 
|---|
| 1689 | * @returns   linenumber, -1 on error | 
|---|
| 1690 | * @remark    0 based. | 
|---|
| 1691 | */ | 
|---|
| 1692 | long kFileEntry::getLineNumber(void) const | 
|---|
| 1693 | { | 
|---|
| 1694 | long cLines = 0; | 
|---|
| 1695 | char *psz = pszFile; | 
|---|
| 1696 |  | 
|---|
| 1697 | while (psz < pszCurrent && *psz != '\0') | 
|---|
| 1698 | { | 
|---|
| 1699 | if (*psz == '\n') | 
|---|
| 1700 | cLines++; | 
|---|
| 1701 | psz++; | 
|---|
| 1702 | } | 
|---|
| 1703 |  | 
|---|
| 1704 | return cLines; | 
|---|
| 1705 | } | 
|---|
| 1706 |  | 
|---|
| 1707 |  | 
|---|
| 1708 | /** | 
|---|
| 1709 | * Creates a variable entry object. | 
|---|
| 1710 | */ | 
|---|
| 1711 | kVariableEntry::kVariableEntry(const char *pszName, const char *pszValue) | 
|---|
| 1712 | { | 
|---|
| 1713 | this->pszName = dupeString(pszName); | 
|---|
| 1714 | this->pszValue = dupeString(pszValue); | 
|---|
| 1715 | } | 
|---|
| 1716 |  | 
|---|
| 1717 |  | 
|---|
| 1718 | /** | 
|---|
| 1719 | * Destroys the variable entry object. | 
|---|
| 1720 | */ | 
|---|
| 1721 | kVariableEntry::~kVariableEntry() | 
|---|
| 1722 | { | 
|---|
| 1723 | if (pszName != NULL) | 
|---|
| 1724 | delete pszName; | 
|---|
| 1725 | if (pszValue != NULL) | 
|---|
| 1726 | delete pszValue; | 
|---|
| 1727 | } | 
|---|
| 1728 |  | 
|---|
| 1729 |  | 
|---|
| 1730 | /** | 
|---|
| 1731 | * Executes the sql query present in pszSql. | 
|---|
| 1732 | * @remark    Throws error code. | 
|---|
| 1733 | */ | 
|---|
| 1734 | void kSqlEntry::dbExecuteQuery(void) throw (kError::enmErrors) | 
|---|
| 1735 | { | 
|---|
| 1736 | pres = ::dbExecuteQuery(pszSql); | 
|---|
| 1737 | if (pres != NULL) | 
|---|
| 1738 | { | 
|---|
| 1739 | cRows = dbQueryResultRows(pres); | 
|---|
| 1740 | dbFetch(); | 
|---|
| 1741 | } | 
|---|
| 1742 | else | 
|---|
| 1743 | throw(kError::error_sql_failed); | 
|---|
| 1744 | } | 
|---|
| 1745 |  | 
|---|
| 1746 |  | 
|---|
| 1747 | /** | 
|---|
| 1748 | * Fetch next row of results. | 
|---|
| 1749 | * @returns   success indicator. TRUE / FASLE. | 
|---|
| 1750 | * @result    lifoVariables are destroyed. | 
|---|
| 1751 | */ | 
|---|
| 1752 | BOOL kSqlEntry::dbFetch(void) | 
|---|
| 1753 | { | 
|---|
| 1754 | BOOL fRc = FALSE; | 
|---|
| 1755 |  | 
|---|
| 1756 | lifoVariables.destroy(); | 
|---|
| 1757 |  | 
|---|
| 1758 | if (cRows != 0) | 
|---|
| 1759 | { | 
|---|
| 1760 | cRows--; | 
|---|
| 1761 | fRc = ::dbFetch(pres, dbFetchCallBack, (void*)&lifoVariables); | 
|---|
| 1762 | } | 
|---|
| 1763 |  | 
|---|
| 1764 | return fRc; | 
|---|
| 1765 | } | 
|---|
| 1766 |  | 
|---|
| 1767 |  | 
|---|
| 1768 | /** | 
|---|
| 1769 | * Callback function used when receiving data from a dbFetch call. | 
|---|
| 1770 | * This function creates a new kVariableEntry from the input, and pushes it | 
|---|
| 1771 | * onto the variable lifo. | 
|---|
| 1772 | * @returns   0  success, -1 error. | 
|---|
| 1773 | * @param     pszValue      Field value. Used as variable value. | 
|---|
| 1774 | * @param     pszFieldName  Field name. Used as variable name. | 
|---|
| 1775 | * @param     pvUser        Pointer to user defined data, here a variable lifo. | 
|---|
| 1776 | */ | 
|---|
| 1777 | static long _System dbFetchCallBack(const char *pszValue, const char *pszFieldName, void *pvUser) | 
|---|
| 1778 | { | 
|---|
| 1779 | kLIFO<kVariableEntry> *plifoVar = (kLIFO<kVariableEntry> *) pvUser; | 
|---|
| 1780 | kVariableEntry  *pVarEntry; | 
|---|
| 1781 |  | 
|---|
| 1782 | if (pszFieldName == NULL) | 
|---|
| 1783 | return -1; | 
|---|
| 1784 | if (pszValue == NULL) | 
|---|
| 1785 | pszValue = "-NULL-"; | 
|---|
| 1786 | pVarEntry = new kVariableEntry(pszFieldName, pszValue); | 
|---|
| 1787 | if (pVarEntry != NULL) | 
|---|
| 1788 | plifoVar->push(pVarEntry); | 
|---|
| 1789 | else | 
|---|
| 1790 | return -1; | 
|---|
| 1791 | return 0; | 
|---|
| 1792 | } | 
|---|
| 1793 |  | 
|---|
| 1794 |  | 
|---|
| 1795 | /** | 
|---|
| 1796 | * Frees the database result. | 
|---|
| 1797 | * @remark    Called during destruction of object. | 
|---|
| 1798 | */ | 
|---|
| 1799 | void kSqlEntry::dbFreeResult(void) | 
|---|
| 1800 | { | 
|---|
| 1801 | if (pres != NULL) | 
|---|
| 1802 | { | 
|---|
| 1803 | ::dbFreeResult(pres); | 
|---|
| 1804 | pres = NULL; | 
|---|
| 1805 | } | 
|---|
| 1806 | } | 
|---|
| 1807 |  | 
|---|
| 1808 |  | 
|---|
| 1809 | /** | 
|---|
| 1810 | * Creates a dummy sql entry. | 
|---|
| 1811 | */ | 
|---|
| 1812 | kSqlEntry::kSqlEntry() : | 
|---|
| 1813 | pszSql(NULL), pres(NULL), cRows(0), pFileEntry(pFileEntry), pszCurrent(pszCurrent) | 
|---|
| 1814 | { | 
|---|
| 1815 | } | 
|---|
| 1816 |  | 
|---|
| 1817 |  | 
|---|
| 1818 | /** | 
|---|
| 1819 | * Interpret the <!kSql ...> tag and creates an sql entry object from it. | 
|---|
| 1820 | * @param     pszCurrent  Current pointer into the file entry object. | 
|---|
| 1821 | * @param     pFileEntry  Pointer to current file entry object. | 
|---|
| 1822 | * @remark    throws error code. | 
|---|
| 1823 | */ | 
|---|
| 1824 | kSqlEntry::kSqlEntry(const kTag &tag, const char *pszCurrent, const kFileEntry *pFileEntry) throw (kError::enmErrors) | 
|---|
| 1825 | : pszSql(NULL), pres(NULL), cRows(0), pFileEntry(pFileEntry), pszCurrent(pszCurrent) | 
|---|
| 1826 | { | 
|---|
| 1827 | const char *pszSql; | 
|---|
| 1828 |  | 
|---|
| 1829 | /* verify tag */ | 
|---|
| 1830 | if (!tag.isTag("!kSql")) | 
|---|
| 1831 | throw(kError::error_invalid_tag); | 
|---|
| 1832 | if (!tag.queryExists("sql")) | 
|---|
| 1833 | throw(kError::error_missing_sql); | 
|---|
| 1834 | if (tag.getParameterCount() > 1) | 
|---|
| 1835 | throw(kError::error_incorrect_number_of_parameters); | 
|---|
| 1836 |  | 
|---|
| 1837 | /* get sql */ | 
|---|
| 1838 | pszSql = tag.queryParameter("sql"); | 
|---|
| 1839 | if (pszSql == NULL || strlen(pszSql) == 0) | 
|---|
| 1840 | throw(kError::error_invalid_sql_tag); | 
|---|
| 1841 |  | 
|---|
| 1842 | this->pszSql = dupeString(pszSql); | 
|---|
| 1843 | if (this->pszSql == NULL) | 
|---|
| 1844 | throw(kError::error_new_failed); | 
|---|
| 1845 |  | 
|---|
| 1846 | /* execute sql */ | 
|---|
| 1847 | dbExecuteQuery(); | 
|---|
| 1848 | } | 
|---|
| 1849 |  | 
|---|
| 1850 |  | 
|---|
| 1851 | /** | 
|---|
| 1852 | * Destructor. | 
|---|
| 1853 | */ | 
|---|
| 1854 | kSqlEntry::~kSqlEntry() | 
|---|
| 1855 | { | 
|---|
| 1856 | if (pszSql != NULL) | 
|---|
| 1857 | delete pszSql; | 
|---|
| 1858 | dbFreeResult(); | 
|---|
| 1859 | } | 
|---|
| 1860 |  | 
|---|
| 1861 |  | 
|---|
| 1862 | /** | 
|---|
| 1863 | * Equal operator. Comapres this object with a key string. | 
|---|
| 1864 | * @returns   TRUE if equal, FALSE if not equal. | 
|---|
| 1865 | * @param     psz  Pointer to key string. | 
|---|
| 1866 | */ | 
|---|
| 1867 | BOOL kSqlEntry::operator ==(const char *psz) const | 
|---|
| 1868 | { | 
|---|
| 1869 | return lifoVariables.find(psz) != NULL; | 
|---|
| 1870 | } | 
|---|
| 1871 |  | 
|---|
| 1872 |  | 
|---|
| 1873 | /** | 
|---|
| 1874 | * Fetches the next set of data. | 
|---|
| 1875 | * @returns   Success indicator. TRUE / FALSE. | 
|---|
| 1876 | */ | 
|---|
| 1877 | BOOL kSqlEntry::fetch(void) | 
|---|
| 1878 | { | 
|---|
| 1879 | return dbFetch(); | 
|---|
| 1880 | } | 
|---|
| 1881 |  | 
|---|
| 1882 |  | 
|---|
| 1883 | /** | 
|---|
| 1884 | * Finds a kVariableEntry matching a given key. | 
|---|
| 1885 | * @returns   Const pointer to variable node or NULL (if not found). | 
|---|
| 1886 | * @param     pszKey  Key to match. | 
|---|
| 1887 | */ | 
|---|
| 1888 | const kVariableEntry *kSqlEntry::find(const char *pszKey) const | 
|---|
| 1889 | { | 
|---|
| 1890 | return lifoVariables.find(pszKey); | 
|---|
| 1891 | } | 
|---|
| 1892 |  | 
|---|
| 1893 |  | 
|---|
| 1894 | /** | 
|---|
| 1895 | * Checks if a node exists. | 
|---|
| 1896 | * @returns   TRUE - node exists, FALSE - node does not exist. | 
|---|
| 1897 | * @param     pVariableEntry  Pointer to node/entry. | 
|---|
| 1898 | */ | 
|---|
| 1899 | BOOL kSqlEntry::exists(const kVariableEntry *pVariableEntry) const | 
|---|
| 1900 | { | 
|---|
| 1901 | return lifoVariables.exists(pVariableEntry); | 
|---|
| 1902 | } | 
|---|
| 1903 |  | 
|---|
| 1904 |  | 
|---|
| 1905 | /** | 
|---|
| 1906 | * Gets last sql error. | 
|---|
| 1907 | * @returns   Pointer to readonly string describing the error. | 
|---|
| 1908 | */ | 
|---|
| 1909 | const char *kSqlEntry::querySqlLastError(void) | 
|---|
| 1910 | { | 
|---|
| 1911 | return dbGetLastErrorDesc(); | 
|---|
| 1912 | } | 
|---|
| 1913 |  | 
|---|
| 1914 |  | 
|---|
| 1915 | /** | 
|---|
| 1916 | * Finds an item in the sublist of the nodes.. Matching a given key. | 
|---|
| 1917 | * @returns   Pointer to subnode if found. | 
|---|
| 1918 | * @param     pszKey  Key to match. | 
|---|
| 1919 | * @remark    uses the const EntryEntry *find(const char *pszKey) const; function. | 
|---|
| 1920 | */ | 
|---|
| 1921 | template <class kEntry, class kEntryEntry> | 
|---|
| 1922 | const kEntryEntry *kLIFO2<kEntry, kEntryEntry>::findSub(const char *pszKey) const | 
|---|
| 1923 | { | 
|---|
| 1924 | const kEntry *pE = pTop; | 
|---|
| 1925 | const kEntryEntry *pEE = NULL; | 
|---|
| 1926 |  | 
|---|
| 1927 | while (pE != NULL && (pEE = pE->find(pszKey)) == NULL) | 
|---|
| 1928 | pE = (const kEntry*)pE->getNext(); | 
|---|
| 1929 |  | 
|---|
| 1930 | return pEE; | 
|---|
| 1931 | } | 
|---|
| 1932 |  | 
|---|
| 1933 |  | 
|---|
| 1934 | /** | 
|---|
| 1935 | * Checks if an item exists. | 
|---|
| 1936 | * @returns   TRUE - exists, FALSE - doesn't exists | 
|---|
| 1937 | * @param     pEntryEntry  Pointer to sub not which is to exists. | 
|---|
| 1938 | * @remark    uses the BOOL exist(const char *pszKey) const; function. | 
|---|
| 1939 | */ | 
|---|
| 1940 | template <class kEntry, class kEntryEntry> | 
|---|
| 1941 | BOOL  kLIFO2<kEntry, kEntryEntry>::existsSub(const kEntryEntry *pEntryEntry) const | 
|---|
| 1942 | { | 
|---|
| 1943 | kEntry *pE = pTop; | 
|---|
| 1944 | BOOL    f= FALSE; | 
|---|
| 1945 |  | 
|---|
| 1946 | while (pE != NULL && !(f = pE->exists(pEntryEntry))) | 
|---|
| 1947 | pE = (kEntry *)pE->getNext(); | 
|---|
| 1948 |  | 
|---|
| 1949 | return f; | 
|---|
| 1950 | } | 
|---|
| 1951 |  | 
|---|
| 1952 |  | 
|---|
| 1953 | /** | 
|---|
| 1954 | * BOOL operator. | 
|---|
| 1955 | */ | 
|---|
| 1956 | BOOL kGraphData::operator==(const kGraphData &entry) const | 
|---|
| 1957 | { | 
|---|
| 1958 | return rdX == entry.rdX; | 
|---|
| 1959 | } | 
|---|
| 1960 |  | 
|---|
| 1961 |  | 
|---|
| 1962 | /** | 
|---|
| 1963 | * BOOL operator. | 
|---|
| 1964 | */ | 
|---|
| 1965 | BOOL kGraphData::operator!=(const kGraphData &entry) const | 
|---|
| 1966 | { | 
|---|
| 1967 | return rdX != entry.rdX; | 
|---|
| 1968 | } | 
|---|
| 1969 |  | 
|---|
| 1970 |  | 
|---|
| 1971 | /** | 
|---|
| 1972 | * BOOL operator. | 
|---|
| 1973 | */ | 
|---|
| 1974 | BOOL kGraphData::operator< (const kGraphData &entry) const | 
|---|
| 1975 | { | 
|---|
| 1976 | return rdX < entry.rdX; | 
|---|
| 1977 | } | 
|---|
| 1978 |  | 
|---|
| 1979 |  | 
|---|
| 1980 | /** | 
|---|
| 1981 | * BOOL operator. | 
|---|
| 1982 | */ | 
|---|
| 1983 | BOOL kGraphData::operator<=(const kGraphData &entry) const | 
|---|
| 1984 | { | 
|---|
| 1985 | return rdX <= entry.rdX; | 
|---|
| 1986 | } | 
|---|
| 1987 |  | 
|---|
| 1988 |  | 
|---|
| 1989 | /** | 
|---|
| 1990 | * BOOL operator. | 
|---|
| 1991 | */ | 
|---|
| 1992 | BOOL kGraphData::operator> (const kGraphData &entry) const | 
|---|
| 1993 | { | 
|---|
| 1994 | return rdX > entry.rdX; | 
|---|
| 1995 | } | 
|---|
| 1996 |  | 
|---|
| 1997 |  | 
|---|
| 1998 | /** | 
|---|
| 1999 | * BOOL operator. | 
|---|
| 2000 | */ | 
|---|
| 2001 | BOOL kGraphData::operator>=(const kGraphData &entry) const | 
|---|
| 2002 | { | 
|---|
| 2003 | return rdX >= entry.rdX; | 
|---|
| 2004 | } | 
|---|
| 2005 |  | 
|---|
| 2006 |  | 
|---|
| 2007 | /** | 
|---|
| 2008 | * Adds a warning to the list of warnings. | 
|---|
| 2009 | * @param     enmErrorCd  Warning code. | 
|---|
| 2010 | */ | 
|---|
| 2011 | void kGraphDataSet::addWarning(kError::enmErrors enmErrorCd) | 
|---|
| 2012 | { | 
|---|
| 2013 | if (plistWarnings != NULL) | 
|---|
| 2014 | plistWarnings->insert(new kWarningEntry(enmErrorCd)); | 
|---|
| 2015 | else | 
|---|
| 2016 | assert(!"internal error"); | 
|---|
| 2017 | } | 
|---|
| 2018 |  | 
|---|
| 2019 |  | 
|---|
| 2020 | /** | 
|---|
| 2021 | * Constructs an empty dataset. | 
|---|
| 2022 | * @remark    Throws kError::enmErrors | 
|---|
| 2023 | */ | 
|---|
| 2024 | kGraphDataSet::kGraphDataSet() throw(kError::enmErrors) | 
|---|
| 2025 | : rdCount(_NAN), ulColor(0xffffffffUL), clrColor(-1), pszLegend(NULL), | 
|---|
| 2026 | fXDate(FALSE), plistWarnings(NULL) | 
|---|
| 2027 | { | 
|---|
| 2028 | } | 
|---|
| 2029 |  | 
|---|
| 2030 |  | 
|---|
| 2031 | /** | 
|---|
| 2032 | * Constructs a dataset from a sql statement and a given graph type. | 
|---|
| 2033 | * @param     pszSql         Sql-statement which gives us the data. | 
|---|
| 2034 | * @param     enmTypeCd      This is the integer value of the graph type. | 
|---|
| 2035 | * @param     plistWarnings  Pointer to warning list. | 
|---|
| 2036 | * @remark    Throws kError::enmErrors | 
|---|
| 2037 | */ | 
|---|
| 2038 | kGraphDataSet::kGraphDataSet(const char *pszSql, int enmTypeCd, | 
|---|
| 2039 | kSortedList<kWarningEntry> *plistWarnings) throw(kError::enmErrors) | 
|---|
| 2040 | : rdCount(_NAN), ulColor(0xffffffffUL), clrColor(-1), pszLegend(NULL), | 
|---|
| 2041 | fXDate(FALSE), plistWarnings(plistWarnings) | 
|---|
| 2042 | { | 
|---|
| 2043 | void *pres; | 
|---|
| 2044 | if (pszSql == NULL || strlen(pszSql) == 0)  throw(kError::error_data_param_is_missing_sql_statement); | 
|---|
| 2045 | if (enmTypeCd == kGraph::unknown)           throw(kError::error_graph_type_must_be_specified_before_data); | 
|---|
| 2046 |  | 
|---|
| 2047 | switch (enmTypeCd) | 
|---|
| 2048 | { | 
|---|
| 2049 | case kGraph::lines: | 
|---|
| 2050 | { | 
|---|
| 2051 | pres = ::dbExecuteQuery(pszSql); | 
|---|
| 2052 | if (pres != NULL) | 
|---|
| 2053 | { | 
|---|
| 2054 | GRAPHCALLBACKPARAM Param = {NULL, this, NULL, (kGraph::enmType)enmTypeCd, 0}; | 
|---|
| 2055 | while (::dbFetch(pres, dbDataSetCallBack, (void*)&Param)) | 
|---|
| 2056 | Param.lSeqNbr = 0; | 
|---|
| 2057 | } | 
|---|
| 2058 | else | 
|---|
| 2059 | throw(kError::error_sql_failed); | 
|---|
| 2060 | break; | 
|---|
| 2061 | } | 
|---|
| 2062 |  | 
|---|
| 2063 | case kGraph::pie: | 
|---|
| 2064 | addWarning(kError::warning_pie_not_implemented_yet); | 
|---|
| 2065 |  | 
|---|
| 2066 | default: | 
|---|
| 2067 | break; | 
|---|
| 2068 | } | 
|---|
| 2069 | } | 
|---|
| 2070 |  | 
|---|
| 2071 |  | 
|---|
| 2072 | /** | 
|---|
| 2073 | * Callback function used when receiving data. | 
|---|
| 2074 | * @returns   0  success, -1 error. | 
|---|
| 2075 | * @param     pszValue      Field value. Used as variable value. | 
|---|
| 2076 | * @param     pszFieldName  Field name. Used as variable name. | 
|---|
| 2077 | * @param     pvUser        Pointer to user defined data, here a variable lifo. | 
|---|
| 2078 | */ | 
|---|
| 2079 | long _System dbDataSetCallBack(const char *pszValue, const char *pszFieldName, void *pvUser) | 
|---|
| 2080 | { | 
|---|
| 2081 | PGRAPHCALLBACKPARAM pParam = (PGRAPHCALLBACKPARAM)pvUser; | 
|---|
| 2082 |  | 
|---|
| 2083 | assert(pParam != NULL); | 
|---|
| 2084 |  | 
|---|
| 2085 | switch (pParam->enmTypeCd) | 
|---|
| 2086 | { | 
|---|
| 2087 | case kGraph::lines: | 
|---|
| 2088 | { | 
|---|
| 2089 | switch (pParam->lSeqNbr) | 
|---|
| 2090 | { | 
|---|
| 2091 | case 0: | 
|---|
| 2092 | pParam->pData = new kGraphData; | 
|---|
| 2093 | /* date test */ | 
|---|
| 2094 | if (strlen(pszValue) == (4+1+2+1+2) && pszValue[4] == '-' && pszValue[7] == '-') | 
|---|
| 2095 | { | 
|---|
| 2096 | strcpy(&pParam->pData->szXDate[0], pszValue); | 
|---|
| 2097 | pParam->pData->rdX = kGraph::dateToDbl(&pParam->pData->szXDate[0]); | 
|---|
| 2098 | pParam->pDataSet->fXDate = TRUE; | 
|---|
| 2099 | } | 
|---|
| 2100 | else | 
|---|
| 2101 | { | 
|---|
| 2102 | pParam->pData->szXDate[0] = '\0'; | 
|---|
| 2103 | pParam->pData->rdX = atol(pszValue); | 
|---|
| 2104 | } | 
|---|
| 2105 | pParam->pDataSet->listData.insert(pParam->pData); | 
|---|
| 2106 | break; | 
|---|
| 2107 |  | 
|---|
| 2108 | case 1: | 
|---|
| 2109 | pParam->pData->rdY = atol(pszValue); | 
|---|
| 2110 | break; | 
|---|
| 2111 |  | 
|---|
| 2112 | case 2: | 
|---|
| 2113 | if (pszFieldName == NULL || stricmp(pszFieldName, "legend") != 0) | 
|---|
| 2114 | pParam->pDataSet->setColor(pszValue); | 
|---|
| 2115 | else | 
|---|
| 2116 | pParam->pDataSet->setLegend(pszValue); | 
|---|
| 2117 | break; | 
|---|
| 2118 |  | 
|---|
| 2119 | case 3: | 
|---|
| 2120 | if (pszFieldName == NULL || stricmp(pszFieldName, "color") != 0) | 
|---|
| 2121 | pParam->pDataSet->setLegend(pszValue); | 
|---|
| 2122 | else | 
|---|
| 2123 | pParam->pDataSet->setColor(pszValue); | 
|---|
| 2124 | break; | 
|---|
| 2125 |  | 
|---|
| 2126 | default: | 
|---|
| 2127 | pParam->pDataSet->addWarning(kError::warning_to_many_fields_in_data_sql); | 
|---|
| 2128 | } | 
|---|
| 2129 | break; | 
|---|
| 2130 | } | 
|---|
| 2131 |  | 
|---|
| 2132 | case kGraph::pie: | 
|---|
| 2133 | default: | 
|---|
| 2134 | break; | 
|---|
| 2135 | } | 
|---|
| 2136 |  | 
|---|
| 2137 | pParam->lSeqNbr++; | 
|---|
| 2138 | return 0; | 
|---|
| 2139 | } | 
|---|
| 2140 |  | 
|---|
| 2141 |  | 
|---|
| 2142 | /** | 
|---|
| 2143 | * Destructor. | 
|---|
| 2144 | */ | 
|---|
| 2145 | kGraphDataSet::~kGraphDataSet(void) | 
|---|
| 2146 | { | 
|---|
| 2147 | if (pszLegend != NULL) delete pszLegend; | 
|---|
| 2148 | } | 
|---|
| 2149 |  | 
|---|
| 2150 |  | 
|---|
| 2151 | /** | 
|---|
| 2152 | * Find max X value in set. | 
|---|
| 2153 | * @returns   max X value. 0.0 if empty set. | 
|---|
| 2154 | */ | 
|---|
| 2155 | double kGraphDataSet::maxX(void) const | 
|---|
| 2156 | { | 
|---|
| 2157 | double rdRet = _NAN; | 
|---|
| 2158 | kGraphData *p = listData.getFirst(); | 
|---|
| 2159 |  | 
|---|
| 2160 | while (p != NULL) | 
|---|
| 2161 | { | 
|---|
| 2162 | if (rdRet < p->rdX || rdRet != rdRet) | 
|---|
| 2163 | rdRet = p->rdX; | 
|---|
| 2164 | p = (kGraphData*)p->getNext(); | 
|---|
| 2165 | } | 
|---|
| 2166 |  | 
|---|
| 2167 | return rdRet == rdRet ? rdRet : 0.0; | 
|---|
| 2168 | } | 
|---|
| 2169 |  | 
|---|
| 2170 |  | 
|---|
| 2171 | /** | 
|---|
| 2172 | * Find min X value in set. | 
|---|
| 2173 | * @returns   min X value. 0.0 if empty set. | 
|---|
| 2174 | */ | 
|---|
| 2175 | double kGraphDataSet::minX(void) const | 
|---|
| 2176 | { | 
|---|
| 2177 | double rdRet = _NAN; | 
|---|
| 2178 | kGraphData *p = listData.getFirst(); | 
|---|
| 2179 |  | 
|---|
| 2180 | while (p != NULL) | 
|---|
| 2181 | { | 
|---|
| 2182 | if (rdRet > p->rdX || rdRet != rdRet) | 
|---|
| 2183 | rdRet = p->rdX; | 
|---|
| 2184 | p = (kGraphData*)p->getNext(); | 
|---|
| 2185 | } | 
|---|
| 2186 |  | 
|---|
| 2187 | return rdRet == rdRet ? rdRet : 0.0; | 
|---|
| 2188 | } | 
|---|
| 2189 |  | 
|---|
| 2190 |  | 
|---|
| 2191 | /** | 
|---|
| 2192 | * Find max Y value in set. | 
|---|
| 2193 | * @returns   max Y value. 0.0 if empty set. | 
|---|
| 2194 | */ | 
|---|
| 2195 | double kGraphDataSet::maxY(void) const | 
|---|
| 2196 | { | 
|---|
| 2197 | double rdRet = _NAN; | 
|---|
| 2198 | kGraphData *p = listData.getFirst(); | 
|---|
| 2199 |  | 
|---|
| 2200 | while (p != NULL) | 
|---|
| 2201 | { | 
|---|
| 2202 | if (rdRet < p->rdY || rdRet != rdRet) | 
|---|
| 2203 | rdRet = p->rdY; | 
|---|
| 2204 | p = (kGraphData*)p->getNext(); | 
|---|
| 2205 | } | 
|---|
| 2206 |  | 
|---|
| 2207 | return rdRet == rdRet ? rdRet : 0.0; | 
|---|
| 2208 | } | 
|---|
| 2209 |  | 
|---|
| 2210 |  | 
|---|
| 2211 | /** | 
|---|
| 2212 | * Find min Y value in set. | 
|---|
| 2213 | * @returns   min Y value. 0.0 if empty set. | 
|---|
| 2214 | */ | 
|---|
| 2215 | double kGraphDataSet::minY(void) const | 
|---|
| 2216 | { | 
|---|
| 2217 | double rdRet = _NAN; | 
|---|
| 2218 | kGraphData *p = listData.getFirst(); | 
|---|
| 2219 |  | 
|---|
| 2220 | while (p != NULL) | 
|---|
| 2221 | { | 
|---|
| 2222 | if (rdRet > p->rdY || rdRet != rdRet) | 
|---|
| 2223 | rdRet = p->rdY; | 
|---|
| 2224 | p = (kGraphData*)p->getNext(); | 
|---|
| 2225 | } | 
|---|
| 2226 |  | 
|---|
| 2227 | return rdRet == rdRet ? rdRet : 0.0; | 
|---|
| 2228 | } | 
|---|
| 2229 |  | 
|---|
| 2230 |  | 
|---|
| 2231 | /** | 
|---|
| 2232 | * Sets the ulColor data member. This | 
|---|
| 2233 | * @param     pszColor  Pointer to color string. That is "#RRGGBB". | 
|---|
| 2234 | */ | 
|---|
| 2235 | void kGraphDataSet::setColor(const char *pszColor) | 
|---|
| 2236 | { | 
|---|
| 2237 | if (ulColor != 0xffffffffUL) | 
|---|
| 2238 | return; | 
|---|
| 2239 |  | 
|---|
| 2240 | if (*pszColor == '#') | 
|---|
| 2241 | { | 
|---|
| 2242 | ulColor = 0; | 
|---|
| 2243 | for (int i = 1; i < 7; i++) | 
|---|
| 2244 | { | 
|---|
| 2245 | ulColor = ulColor << 4; | 
|---|
| 2246 | if (pszColor[i] >= '0' && pszColor[i] <= '9') | 
|---|
| 2247 | ulColor |= pszColor[i] - '0'; | 
|---|
| 2248 | else if (pszColor[i] >= 'A' && pszColor[i] <= 'F') | 
|---|
| 2249 | ulColor |= pszColor[i] - 'A' + 0xa; | 
|---|
| 2250 | else if (pszColor[i] >= 'a' && pszColor[i] <= 'f') | 
|---|
| 2251 | ulColor |= pszColor[i] - 'a' + 0xa; | 
|---|
| 2252 | else | 
|---|
| 2253 | addWarning(kError::warning_invalid_color_value); | 
|---|
| 2254 | } | 
|---|
| 2255 | } | 
|---|
| 2256 | else | 
|---|
| 2257 | addWarning(kError::warning_invalid_color_value); | 
|---|
| 2258 | } | 
|---|
| 2259 |  | 
|---|
| 2260 |  | 
|---|
| 2261 | /** | 
|---|
| 2262 | * Allocates color and set the clrColor datamember. | 
|---|
| 2263 | * @param     pGraph  Pointer to gifdraw image structure. | 
|---|
| 2264 | */ | 
|---|
| 2265 | void kGraphDataSet::setColor(gdImagePtr pGraph) | 
|---|
| 2266 | { | 
|---|
| 2267 | if (clrColor == -1) | 
|---|
| 2268 | clrColor = gdImageColorAllocate(pGraph, | 
|---|
| 2269 | (int)(0xFF & (ulColor >> 16)), | 
|---|
| 2270 | (int)(0xFF & (ulColor >> 8)), | 
|---|
| 2271 | (int)(0xFF & ulColor)); | 
|---|
| 2272 | } | 
|---|
| 2273 |  | 
|---|
| 2274 |  | 
|---|
| 2275 | /** | 
|---|
| 2276 | * Sets the legend string. | 
|---|
| 2277 | * @param     pszLegend  Legend. | 
|---|
| 2278 | */ | 
|---|
| 2279 | void kGraphDataSet::setLegend(const char *pszLegend) | 
|---|
| 2280 | { | 
|---|
| 2281 | if (this->pszLegend == NULL) | 
|---|
| 2282 | this->pszLegend = dupeString(pszLegend); | 
|---|
| 2283 | } | 
|---|
| 2284 |  | 
|---|
| 2285 |  | 
|---|
| 2286 | /** | 
|---|
| 2287 | * Analyses the tag and executes SQL statements. | 
|---|
| 2288 | * @param     tag         Tag. | 
|---|
| 2289 | * @param     pszBaseDir  Base output directory. | 
|---|
| 2290 | * @remark    Throws kError::enmErrors | 
|---|
| 2291 | */ | 
|---|
| 2292 | void  kGraph::analyseTag(const kTag &tag, const char *pszBaseDir) throw(kError::enmErrors) | 
|---|
| 2293 | { | 
|---|
| 2294 | int cArgs,    i; | 
|---|
| 2295 | const char    *pszName; | 
|---|
| 2296 | const char    *pszValue; | 
|---|
| 2297 | /*const char    *psz; | 
|---|
| 2298 | long           l; | 
|---|
| 2299 | unsigned long  ul;*/ | 
|---|
| 2300 |  | 
|---|
| 2301 | /* tagname */ | 
|---|
| 2302 | if (stricmp(tag.getTagname(), "!kGraph") != 0) | 
|---|
| 2303 | throw(kError::error_invalid_tagname); | 
|---|
| 2304 |  | 
|---|
| 2305 | /* parameters */ | 
|---|
| 2306 | i = 0; | 
|---|
| 2307 | cArgs = (int)tag.getParameterCount(); | 
|---|
| 2308 | while (i < cArgs) | 
|---|
| 2309 | { | 
|---|
| 2310 | pszName  = tag.queryParameterName(i); | 
|---|
| 2311 | pszValue = tag.queryParameterValue(i); | 
|---|
| 2312 |  | 
|---|
| 2313 | if (stricmp(pszName, "data") == 0) | 
|---|
| 2314 | { | 
|---|
| 2315 | if ((int)enmTypeCd == unknown) throw(kError::error_graph_type_must_be_specified_before_data); | 
|---|
| 2316 | if (pszValue == NULL || strlen(pszValue) == 0) throw(kError::error_data_param_is_missing_value); | 
|---|
| 2317 | #if 0 | 
|---|
| 2318 | listDataSets.insert(new kGraphDataSet(pszValue, enmTypeCd, &listWarnings)); | 
|---|
| 2319 | #else | 
|---|
| 2320 | fetchData(pszValue); | 
|---|
| 2321 | #endif | 
|---|
| 2322 | } | 
|---|
| 2323 | else if (stricmp(pszName, "type") == 0) | 
|---|
| 2324 | { | 
|---|
| 2325 | if (pszValue == NULL) throw(kError::error_type_param_is_missing_value); | 
|---|
| 2326 | if (stricmp(pszValue, "lines") == 0) | 
|---|
| 2327 | enmTypeCd = lines; | 
|---|
| 2328 | else if (stricmp(pszValue, "pie") == 0) | 
|---|
| 2329 | enmTypeCd = pie; | 
|---|
| 2330 | else | 
|---|
| 2331 | throw(kError::error_invalid_type); | 
|---|
| 2332 |  | 
|---|
| 2333 | } | 
|---|
| 2334 | else if (stricmp(pszName, "subtype") == 0) | 
|---|
| 2335 | { | 
|---|
| 2336 | if (pszValue != NULL && stricmp(pszValue, "normal") == 0) | 
|---|
| 2337 | enmSubTypeCd = normal; | 
|---|
| 2338 | else | 
|---|
| 2339 | addWarning(kError::warning_invalid_sub_type); | 
|---|
| 2340 | } | 
|---|
| 2341 | else if (stricmp(pszName, "filename") == 0) | 
|---|
| 2342 | { | 
|---|
| 2343 | if (pszValue == NULL || strlen(pszValue) == 0) throw(kError::error_filename_param_is_missing_value); | 
|---|
| 2344 | pszFilename = new char[strlen(pszValue) + 2 + strlen(pszBaseDir)]; | 
|---|
| 2345 | if (pszFilename == NULL) throw(kError::error_filename_param_is_missing_value); | 
|---|
| 2346 | sprintf(pszFilename, "%s\\%s", pszBaseDir, pszValue); | 
|---|
| 2347 | } | 
|---|
| 2348 | else if (stricmp(pszName, "title") == 0) | 
|---|
| 2349 | { | 
|---|
| 2350 | if (pszValue != NULL) | 
|---|
| 2351 | pszTitle = dupeString(pszValue); | 
|---|
| 2352 | else | 
|---|
| 2353 | addWarning(kError::warning_title_param_is_missing_value); | 
|---|
| 2354 | } | 
|---|
| 2355 | else if (stricmp(pszName, "titlex") == 0) | 
|---|
| 2356 | { | 
|---|
| 2357 | if (pszValue != NULL) | 
|---|
| 2358 | pszTitleX = dupeString(pszValue); | 
|---|
| 2359 | else | 
|---|
| 2360 | addWarning(kError::warning_titlex_param_is_missing_value); | 
|---|
| 2361 | } | 
|---|
| 2362 | else if (stricmp(pszName, "titley") == 0) | 
|---|
| 2363 | { | 
|---|
| 2364 | if (pszValue != NULL) | 
|---|
| 2365 | pszTitleY = dupeString(pszValue); | 
|---|
| 2366 | else | 
|---|
| 2367 | addWarning(kError::warning_titley_param_is_missing_value); | 
|---|
| 2368 | } | 
|---|
| 2369 | else if (stricmp(pszName, "legend") == 0) | 
|---|
| 2370 | { | 
|---|
| 2371 | fLegend = pszValue == NULL || stricmp(pszValue, "yes") == 0; | 
|---|
| 2372 | } | 
|---|
| 2373 | else if (stricmp(pszName, "width") == 0 || stricmp(pszName, "cx") == 0) | 
|---|
| 2374 | { | 
|---|
| 2375 | if (pszValue == NULL || strlen(pszValue) == 0) throw(kError::error_width_cx_param_is_missing_value); | 
|---|
| 2376 | cX = atol(pszValue); | 
|---|
| 2377 | if (cX < 100) | 
|---|
| 2378 | throw(kError::error_graph_to_small); | 
|---|
| 2379 | } | 
|---|
| 2380 | else if (stricmp(pszName, "height") == 0 || stricmp(pszName, "cy") == 0) | 
|---|
| 2381 | { | 
|---|
| 2382 | if (pszValue == NULL || strlen(pszValue) == 0) throw(kError::error_height_cy_param_is_missing_value); | 
|---|
| 2383 | cY = atol(pszValue); | 
|---|
| 2384 | if (cY < 100) | 
|---|
| 2385 | throw(kError::error_graph_to_small); | 
|---|
| 2386 | } | 
|---|
| 2387 | else if (stricmp(pszName, "startx") == 0 || stricmp(pszName, "minx") == 0) | 
|---|
| 2388 | { | 
|---|
| 2389 | if (pszValue == NULL || strlen(pszValue) == 0) throw(kError::error_xstart_param_is_missing_value); | 
|---|
| 2390 | if (isDate(pszValue)) | 
|---|
| 2391 | rdStartX = dateToDbl(pszValue); | 
|---|
| 2392 | else | 
|---|
| 2393 | rdStartX = (double)atol(pszValue); /* TODO: real value not supported */ | 
|---|
| 2394 | } | 
|---|
| 2395 | else if (stricmp(pszName, "endx") == 0 || stricmp(pszName, "maxx") == 0) | 
|---|
| 2396 | { | 
|---|
| 2397 | if (pszValue == NULL || strlen(pszValue) == 0) throw(kError::error_xend_param_is_missing_value); | 
|---|
| 2398 | if (isDate(pszValue)) | 
|---|
| 2399 | rdEndX = dateToDbl(pszValue); | 
|---|
| 2400 | else | 
|---|
| 2401 | rdEndX = (double)atol(pszValue); /* TODO: real value not supported */ | 
|---|
| 2402 | } | 
|---|
| 2403 | else if (stricmp(pszName, "starty") == 0 || stricmp(pszName, "miny") == 0) | 
|---|
| 2404 | { | 
|---|
| 2405 | if (pszValue == NULL || strlen(pszValue) == 0) throw(kError::error_ystart_param_is_missing_value); | 
|---|
| 2406 | rdStartY = (double)atol(pszValue); /* TODO: real value not supported */ | 
|---|
| 2407 | } | 
|---|
| 2408 | else if (stricmp(pszName, "endy") == 0 || stricmp(pszName, "maxy") == 0) | 
|---|
| 2409 | { | 
|---|
| 2410 | if (pszValue == NULL || strlen(pszValue) == 0) throw(kError::error_yend_param_is_missing_value); | 
|---|
| 2411 | rdEndY = (double)atol(pszValue); /* TODO: real value not supported */ | 
|---|
| 2412 | } | 
|---|
| 2413 | else if (stricmp(pszName, "background") == 0) | 
|---|
| 2414 | { | 
|---|
| 2415 | if (pszValue != NULL) | 
|---|
| 2416 | { | 
|---|
| 2417 | if (pszValue[0] == '#') | 
|---|
| 2418 | ulBGColor = readColor(pszValue); | 
|---|
| 2419 | else | 
|---|
| 2420 | pszBackground = dupeString(pszValue); | 
|---|
| 2421 | } | 
|---|
| 2422 | else | 
|---|
| 2423 | addWarning(kError::warning_background_param_is_missing_value); | 
|---|
| 2424 | } | 
|---|
| 2425 | else if (stricmp(pszName, "backgroundcolor") == 0) | 
|---|
| 2426 | { | 
|---|
| 2427 | if (pszValue != NULL) | 
|---|
| 2428 | { | 
|---|
| 2429 | if (pszValue[0] == '#') | 
|---|
| 2430 | ulBGColor = readColor(pszValue); | 
|---|
| 2431 | else | 
|---|
| 2432 | addWarning(kError::warning_backgroundcolor_is_invalid); | 
|---|
| 2433 | } | 
|---|
| 2434 | else | 
|---|
| 2435 | addWarning(kError::warning_backgroundcolor_param_is_missing_value); | 
|---|
| 2436 | } | 
|---|
| 2437 | else if (stricmp(pszName, "foregroundcolor") == 0) | 
|---|
| 2438 | { | 
|---|
| 2439 | if (pszValue != NULL) | 
|---|
| 2440 | { | 
|---|
| 2441 | if (pszValue[0] == '#') | 
|---|
| 2442 | ulFGColor = readColor(pszValue); | 
|---|
| 2443 | else | 
|---|
| 2444 | addWarning(kError::warning_foregroundcolor_is_invalid); | 
|---|
| 2445 | } | 
|---|
| 2446 | else | 
|---|
| 2447 | addWarning(kError::warning_foregroundcolor_param_is_missing_value); | 
|---|
| 2448 | } | 
|---|
| 2449 | else if (stricmp(pszName, "axiscolor") == 0) | 
|---|
| 2450 | { | 
|---|
| 2451 | if (pszValue != NULL) | 
|---|
| 2452 | { | 
|---|
| 2453 | if (pszValue[0] == '#') | 
|---|
| 2454 | ulAxisColor = readColor(pszValue); | 
|---|
| 2455 | else | 
|---|
| 2456 | addWarning(kError::warning_axiscolor_is_invalid); | 
|---|
| 2457 | } | 
|---|
| 2458 | else | 
|---|
| 2459 | addWarning(kError::warning_axiscolor_param_is_missing_value); | 
|---|
| 2460 | } | 
|---|
| 2461 | else | 
|---|
| 2462 | addWarning(kError::warning_invalid_parameter); | 
|---|
| 2463 |  | 
|---|
| 2464 | /* next */ | 
|---|
| 2465 | i++; | 
|---|
| 2466 | } | 
|---|
| 2467 |  | 
|---|
| 2468 | /* check that required parameters are present */ | 
|---|
| 2469 | if ((int)enmTypeCd == unknown)       throw(kError::error_graph_type_is_missing); | 
|---|
| 2470 | if ((int)enmSubTypeCd != normal)     throw(kError::error_graph_subtype_is_invalid); | 
|---|
| 2471 | if (pszFilename == NULL)             throw(kError::error_filename_is_missing); | 
|---|
| 2472 | if (listDataSets.getFirst() == NULL) throw(kError::error_no_data); | 
|---|
| 2473 | if (cX < 50 || cY < 40)              throw(kError::error_invalid_dimentions); | 
|---|
| 2474 |  | 
|---|
| 2475 | #if 0 | 
|---|
| 2476 | /* Check for date X values */ | 
|---|
| 2477 | fXDate = listDataSets.getFirst()->getXDate(); | 
|---|
| 2478 | #endif | 
|---|
| 2479 | } | 
|---|
| 2480 |  | 
|---|
| 2481 |  | 
|---|
| 2482 | /** | 
|---|
| 2483 | * Fetches data for multiple data sets. | 
|---|
| 2484 | * @param     pszSql  Pointer to sql statement. | 
|---|
| 2485 | */ | 
|---|
| 2486 | void    kGraph::fetchData(const char *pszSql) throw(kError::enmErrors) | 
|---|
| 2487 | { | 
|---|
| 2488 | void *pres; | 
|---|
| 2489 |  | 
|---|
| 2490 | switch (enmTypeCd) | 
|---|
| 2491 | { | 
|---|
| 2492 | case kGraph::lines: | 
|---|
| 2493 | { | 
|---|
| 2494 | pres = ::dbExecuteQuery(pszSql); | 
|---|
| 2495 | if (pres != NULL) | 
|---|
| 2496 | { | 
|---|
| 2497 | kGraphDataSet *pDataSet = NULL; | 
|---|
| 2498 | GRAPHCALLBACKPARAM Param = {this, NULL, NULL, enmTypeCd, 0, NULL, NULL}; | 
|---|
| 2499 | while (::dbFetch(pres, dbGraphCallBack, (void*)&Param)) | 
|---|
| 2500 | { | 
|---|
| 2501 | /* find correct dataset: legend present - allways; else first time only.*/ | 
|---|
| 2502 | if (Param.pszLegend != NULL || pDataSet == NULL) | 
|---|
| 2503 | pDataSet = findOrCreateDataSet(Param.pszLegend); | 
|---|
| 2504 | assert(pDataSet != NULL); | 
|---|
| 2505 |  | 
|---|
| 2506 | pDataSet->setLegend(Param.pszLegend); | 
|---|
| 2507 | pDataSet->setColor(Param.pszColor); | 
|---|
| 2508 | pDataSet->listData.insert(Param.pData); | 
|---|
| 2509 |  | 
|---|
| 2510 | /* next */ | 
|---|
| 2511 | Param.lSeqNbr = 0; | 
|---|
| 2512 | Param.pData = NULL; | 
|---|
| 2513 | if (Param.pszColor != NULL) | 
|---|
| 2514 | { | 
|---|
| 2515 | delete Param.pszColor; | 
|---|
| 2516 | Param.pszColor = NULL; | 
|---|
| 2517 | } | 
|---|
| 2518 | if (Param.pszLegend != NULL) | 
|---|
| 2519 | { | 
|---|
| 2520 | delete Param.pszLegend; | 
|---|
| 2521 | Param.pszLegend = NULL; | 
|---|
| 2522 | } | 
|---|
| 2523 | } | 
|---|
| 2524 | if (Param.pData != NULL) delete Param.pData; | 
|---|
| 2525 | if (Param.pszColor != NULL) delete Param.pszColor; | 
|---|
| 2526 | if (Param.pszLegend != NULL) delete Param.pszLegend; | 
|---|
| 2527 | } | 
|---|
| 2528 | else | 
|---|
| 2529 | throw(kError::error_sql_failed); | 
|---|
| 2530 | break; | 
|---|
| 2531 | } | 
|---|
| 2532 |  | 
|---|
| 2533 | case kGraph::pie: | 
|---|
| 2534 | addWarning(kError::warning_pie_not_implemented_yet); | 
|---|
| 2535 |  | 
|---|
| 2536 | default: | 
|---|
| 2537 | break; | 
|---|
| 2538 | } | 
|---|
| 2539 | } | 
|---|
| 2540 |  | 
|---|
| 2541 |  | 
|---|
| 2542 |  | 
|---|
| 2543 | /** | 
|---|
| 2544 | * Callback function used when receiving data. | 
|---|
| 2545 | * @returns   0  success, -1 error. | 
|---|
| 2546 | * @param     pszValue      Field value. Used as variable value. | 
|---|
| 2547 | * @param     pszFieldName  Field name. Used as variable name. | 
|---|
| 2548 | * @param     pvUser        Pointer to user defined data, here a variable lifo. | 
|---|
| 2549 | */ | 
|---|
| 2550 | long _System dbGraphCallBack(const char *pszValue, const char *pszFieldName, void *pvUser) | 
|---|
| 2551 | { | 
|---|
| 2552 | PGRAPHCALLBACKPARAM pParam = (PGRAPHCALLBACKPARAM)pvUser; | 
|---|
| 2553 |  | 
|---|
| 2554 | assert(pParam != NULL); | 
|---|
| 2555 |  | 
|---|
| 2556 | switch (pParam->enmTypeCd) | 
|---|
| 2557 | { | 
|---|
| 2558 | case kGraph::lines: | 
|---|
| 2559 | { | 
|---|
| 2560 | switch (pParam->lSeqNbr) | 
|---|
| 2561 | { | 
|---|
| 2562 | case 0: | 
|---|
| 2563 | pParam->pData = new kGraphData; | 
|---|
| 2564 | /* date test */ | 
|---|
| 2565 | if (strlen(pszValue) == (4+1+2+1+2) && pszValue[4] == '-' && pszValue[7] == '-') | 
|---|
| 2566 | { | 
|---|
| 2567 | strcpy(&pParam->pData->szXDate[0], pszValue); | 
|---|
| 2568 | pParam->pData->rdX = kGraph::dateToDbl(&pParam->pData->szXDate[0]); | 
|---|
| 2569 | pParam->pGraph->fXDate = TRUE; | 
|---|
| 2570 | } | 
|---|
| 2571 | else | 
|---|
| 2572 | { | 
|---|
| 2573 | pParam->pData->szXDate[0] = '\0'; | 
|---|
| 2574 | pParam->pData->rdX = atol(pszValue); | 
|---|
| 2575 | } | 
|---|
| 2576 | break; | 
|---|
| 2577 |  | 
|---|
| 2578 | case 1: | 
|---|
| 2579 | pParam->pData->rdY = atol(pszValue); | 
|---|
| 2580 | break; | 
|---|
| 2581 |  | 
|---|
| 2582 | case 2: | 
|---|
| 2583 | if (pszFieldName == NULL || stricmp(pszFieldName, "legend") != 0) | 
|---|
| 2584 | pParam->pszColor = dupeString(pszValue); | 
|---|
| 2585 | else | 
|---|
| 2586 | pParam->pszLegend = dupeString(pszValue); | 
|---|
| 2587 | break; | 
|---|
| 2588 |  | 
|---|
| 2589 | case 3: | 
|---|
| 2590 | if (pszFieldName == NULL || stricmp(pszFieldName, "color") != 0) | 
|---|
| 2591 | pParam->pszLegend = dupeString(pszValue); | 
|---|
| 2592 | else | 
|---|
| 2593 | pParam->pszColor = dupeString(pszValue); | 
|---|
| 2594 | break; | 
|---|
| 2595 |  | 
|---|
| 2596 | default: | 
|---|
| 2597 | pParam->pGraph->addWarning(kError::warning_to_many_fields_in_data_sql); | 
|---|
| 2598 | } | 
|---|
| 2599 | break; | 
|---|
| 2600 | } | 
|---|
| 2601 |  | 
|---|
| 2602 | case kGraph::pie: | 
|---|
| 2603 | default: | 
|---|
| 2604 | break; | 
|---|
| 2605 | } | 
|---|
| 2606 |  | 
|---|
| 2607 | pParam->lSeqNbr++; | 
|---|
| 2608 | return 0; | 
|---|
| 2609 | } | 
|---|
| 2610 |  | 
|---|
| 2611 |  | 
|---|
| 2612 | /** | 
|---|
| 2613 | * Finds or creates an dataset for the given legend (id). | 
|---|
| 2614 | * @returns   Pointer to DataSet. (NULL only when new failes.) | 
|---|
| 2615 | * @param     pszLegend   DataSet identifier. NULL is allowed. | 
|---|
| 2616 | */ | 
|---|
| 2617 | kGraphDataSet *kGraph::findOrCreateDataSet(const char *pszLegend) throw(kError::enmErrors) | 
|---|
| 2618 | { | 
|---|
| 2619 | kGraphDataSet *p; | 
|---|
| 2620 |  | 
|---|
| 2621 | if (pszLegend != NULL) | 
|---|
| 2622 | { | 
|---|
| 2623 | p = listDataSets.getFirst(); | 
|---|
| 2624 | while (p != NULL && *p != pszLegend) | 
|---|
| 2625 | p = (kGraphDataSet *)p->getNext(); | 
|---|
| 2626 | } | 
|---|
| 2627 | else | 
|---|
| 2628 | p = NULL; | 
|---|
| 2629 |  | 
|---|
| 2630 |  | 
|---|
| 2631 | if (p == NULL) | 
|---|
| 2632 | listDataSets.insert(p = new kGraphDataSet()); | 
|---|
| 2633 |  | 
|---|
| 2634 | return p; | 
|---|
| 2635 | } | 
|---|
| 2636 |  | 
|---|
| 2637 |  | 
|---|
| 2638 | /** | 
|---|
| 2639 | * Draw the base structure of the graph. | 
|---|
| 2640 | */ | 
|---|
| 2641 | void    kGraph::createBaseGraph(void)       throw(kError::enmErrors) | 
|---|
| 2642 | { | 
|---|
| 2643 | POINTL ptl; | 
|---|
| 2644 | char   szMax[32]; | 
|---|
| 2645 |  | 
|---|
| 2646 | pGraph = gdImageCreate(cX, cY); | 
|---|
| 2647 |  | 
|---|
| 2648 | /* background? */ | 
|---|
| 2649 | if (pszBackground != NULL) | 
|---|
| 2650 | { | 
|---|
| 2651 | gdImagePtr  pBackground; | 
|---|
| 2652 | FILE       *phFile; | 
|---|
| 2653 | phFile = fopen(pszBackground, "rb"); | 
|---|
| 2654 | if (phFile) | 
|---|
| 2655 | { | 
|---|
| 2656 | pBackground = gdImageCreateFromGif(phFile); | 
|---|
| 2657 | if (pBackground != NULL) | 
|---|
| 2658 | { | 
|---|
| 2659 | gdImageCopyResized(pGraph, pBackground, | 
|---|
| 2660 | 0, 0,    //destination low left corner | 
|---|
| 2661 | 0, 0,    //source      low left corner | 
|---|
| 2662 | cX, cY,  //destination width and height | 
|---|
| 2663 | gdImageSX(pBackground), //source width | 
|---|
| 2664 | gdImageSY(pBackground)  //source height | 
|---|
| 2665 | ); | 
|---|
| 2666 | gdImageDestroy(pBackground); | 
|---|
| 2667 | } | 
|---|
| 2668 | else | 
|---|
| 2669 | addWarning(kError::warning_failed_to_load_background_image); | 
|---|
| 2670 | fclose(phFile); | 
|---|
| 2671 | } | 
|---|
| 2672 | else | 
|---|
| 2673 | addWarning(kError::warning_failed_to_open_background_image); | 
|---|
| 2674 | } | 
|---|
| 2675 |  | 
|---|
| 2676 | /* calc base coordinates */ | 
|---|
| 2677 | ptlOrigo.x = max(2 + (fXDate ? 5 : 0)*6, (long)(cX*0.05)); | 
|---|
| 2678 | _itoa((int)maxY(), &szMax[0], 10); | 
|---|
| 2679 | ptlOrigo.y = max((long)(2 + strlen(&szMax[0])*6), (long)(cY*0.05)); | 
|---|
| 2680 | if (pszTitleX) ptlOrigo.y += 16; | 
|---|
| 2681 | if (pszTitleY) ptlOrigo.x += 16; | 
|---|
| 2682 | ptlYEnd.x  = ptlOrigo.x; | 
|---|
| 2683 | ptlYEnd.y  = cY - ptlOrigo.y - (pszTitle ? max(20, (long)(cY*0.10)) : 0); | 
|---|
| 2684 | ptlXEnd.x  = cX - ptlOrigo.x; | 
|---|
| 2685 | ptlXEnd.y  = ptlOrigo.y; | 
|---|
| 2686 |  | 
|---|
| 2687 | if (fLegend) | 
|---|
| 2688 | { | 
|---|
| 2689 | addWarning(kError::warning_legend_is_not_implemented_yet); | 
|---|
| 2690 | ptlXEnd.x -= (long)(cX * 0.20); | 
|---|
| 2691 | } | 
|---|
| 2692 |  | 
|---|
| 2693 | /* allocate default colors */ | 
|---|
| 2694 | setColors(); | 
|---|
| 2695 |  | 
|---|
| 2696 | /* draw axsis */ | 
|---|
| 2697 | if (pszTitleX) | 
|---|
| 2698 | gdImageStringLB(pGraph, gdFontGiant, | 
|---|
| 2699 | (int)(ptlOrigo.x + (ptlXEnd.x - ptlOrigo.x)/2.0 - strlen(pszTitleX)*9/2.0), | 
|---|
| 2700 | max(2, (int)(cY*0.01))+ 16, | 
|---|
| 2701 | pszTitleX, clrForeground); | 
|---|
| 2702 | if (pszTitleY) | 
|---|
| 2703 | gdImageStringUpLB(pGraph, gdFontGiant, | 
|---|
| 2704 | max(2, (int)(cX*0.01)), | 
|---|
| 2705 | (int)(ptlOrigo.y + (ptlYEnd.y - ptlOrigo.y)/2.0 - strlen(pszTitleY)*9/2.0), | 
|---|
| 2706 | pszTitleY, clrForeground); | 
|---|
| 2707 | if (pszTitle) | 
|---|
| 2708 | { | 
|---|
| 2709 | ptl.x = (long)(cX/2.0 - strlen(pszTitle)*9/2.0); | 
|---|
| 2710 | ptl.y = cY - max(5, (int)(cY*0.02)); | 
|---|
| 2711 | gdImageStringLB(pGraph, gdFontGiant, (int)ptl.x, (int)ptl.y, pszTitle, clrForeground); | 
|---|
| 2712 | gdImageLineLB(pGraph, (int)ptl.x - 3, (int)ptl.y - 18, | 
|---|
| 2713 | (int)ptl.x + strlen(pszTitle)*9 + 5, (int)ptl.y - 18, clrForeground); | 
|---|
| 2714 | } | 
|---|
| 2715 |  | 
|---|
| 2716 |  | 
|---|
| 2717 | gdImageLineLB(pGraph, (int)ptlOrigo.x,  (int)ptlOrigo.y-2, (int)ptlYEnd.x, (int)ptlYEnd.y+3, clrAxis); | 
|---|
| 2718 | gdImageLineLB(pGraph, (int)ptlYEnd.x+2, (int)ptlYEnd.y,    (int)ptlYEnd.x, (int)ptlYEnd.y+3, clrAxis); | 
|---|
| 2719 | gdImageLineLB(pGraph, (int)ptlYEnd.x-2, (int)ptlYEnd.y,    (int)ptlYEnd.x, (int)ptlYEnd.y+3, clrAxis); | 
|---|
| 2720 |  | 
|---|
| 2721 | gdImageLineLB(pGraph, (int)ptlOrigo.x-2, (int)ptlOrigo.y,  (int)ptlXEnd.x+3, (int)ptlXEnd.y, clrAxis); | 
|---|
| 2722 | gdImageLineLB(pGraph, (int)ptlXEnd.x,    (int)ptlXEnd.y+2, (int)ptlXEnd.x+3, (int)ptlXEnd.y, clrAxis); | 
|---|
| 2723 | gdImageLineLB(pGraph, (int)ptlXEnd.x,    (int)ptlXEnd.y-2, (int)ptlXEnd.x+3, (int)ptlXEnd.y, clrAxis); | 
|---|
| 2724 |  | 
|---|
| 2725 |  | 
|---|
| 2726 | /* scale - x */ | 
|---|
| 2727 | char    szData[20]; | 
|---|
| 2728 | double  rdMin, rdMax, rd, rdD; | 
|---|
| 2729 | int     cTags; | 
|---|
| 2730 |  | 
|---|
| 2731 | rdMax = maxX(); | 
|---|
| 2732 | rdMin = minX(); | 
|---|
| 2733 |  | 
|---|
| 2734 | if (fXDate) | 
|---|
| 2735 | { | 
|---|
| 2736 | if (!kGraph::dblToDate(rdMin, &szData[0])) | 
|---|
| 2737 | addWarning(kError::warning_failed_to_convert_date); | 
|---|
| 2738 | } | 
|---|
| 2739 | else | 
|---|
| 2740 | sprintf(&szData[0], "%1.*f", rdMax > 10 ? 0 : 1, rdMin); | 
|---|
| 2741 | gdImageStringLB(pGraph, gdFontSmall, | 
|---|
| 2742 | (int)(ptlOrigo.x - strlen(&szData[0])*6/2.0), | 
|---|
| 2743 | (int)(ptlOrigo.y - 3), | 
|---|
| 2744 | &szData[0], clrForeground); | 
|---|
| 2745 | if (fXDate) | 
|---|
| 2746 | { | 
|---|
| 2747 | if (!kGraph::dblToDate(rdMax, &szData[0])) | 
|---|
| 2748 | addWarning(kError::warning_failed_to_convert_date); | 
|---|
| 2749 | } | 
|---|
| 2750 | else | 
|---|
| 2751 | sprintf(&szData[0], "%1.*f", rdMax > 10 ? 0 : 1, rdMax); | 
|---|
| 2752 | gdImageStringLB(pGraph, gdFontSmall, | 
|---|
| 2753 | (int)(ptlXEnd.x - strlen(&szData[0])*6/2.0), | 
|---|
| 2754 | (int)(ptlOrigo.y - 3), | 
|---|
| 2755 | &szData[0], clrForeground); | 
|---|
| 2756 |  | 
|---|
| 2757 | rd    = strlen(&szData[0])*6 + 20;             //length of on scale tag | 
|---|
| 2758 | cTags = (int)((ptlXEnd.x - ptlOrigo.x) / rd);  //max number of tags | 
|---|
| 2759 | if (cTags > 0) | 
|---|
| 2760 | { | 
|---|
| 2761 | rdD = rdMax - rdMin; | 
|---|
| 2762 | if (rd > 10) | 
|---|
| 2763 | rdD = (int)(rdD/cTags); | 
|---|
| 2764 | else | 
|---|
| 2765 | rdD = ((int)(rdD/cTags*10))/10; | 
|---|
| 2766 | rd = rdMin + rdD; | 
|---|
| 2767 | while (rdD > 0.0 && (rd + rdD) <= rdMax) | 
|---|
| 2768 | { | 
|---|
| 2769 | int x = (int)(ptlOrigo.x + (ptlXEnd.x - ptlOrigo.x)/(rdMax-rdMin)*(rd - rdMin)); | 
|---|
| 2770 | if (fXDate) | 
|---|
| 2771 | { | 
|---|
| 2772 | if (!kGraph::dblToDate(rd, &szData[0])) | 
|---|
| 2773 | addWarning(kError::warning_failed_to_convert_date); | 
|---|
| 2774 | } | 
|---|
| 2775 | else | 
|---|
| 2776 | sprintf(&szData[0], "%1.*f", rdMax > 10 ? 0 : 1, rd); | 
|---|
| 2777 | gdImageStringLB(pGraph, gdFontSmall, x - (int)(strlen(&szData[0])*6/2.0), (int)(ptlOrigo.y - 3), | 
|---|
| 2778 | &szData[0], clrForeground); | 
|---|
| 2779 | gdImageLineLB(pGraph, x, (int)(ptlOrigo.y - 1), x, (int)(ptlOrigo.y + 1), clrAxis); | 
|---|
| 2780 |  | 
|---|
| 2781 | /* next */ | 
|---|
| 2782 | rd += rdD; | 
|---|
| 2783 | } | 
|---|
| 2784 | } | 
|---|
| 2785 |  | 
|---|
| 2786 | /* scale - y */ | 
|---|
| 2787 | rdMax = maxY(); | 
|---|
| 2788 | rdMin = minY(); | 
|---|
| 2789 |  | 
|---|
| 2790 | sprintf(&szData[0], "%1.*f", rdMax > 10 ? 0 : 1, rdMin); | 
|---|
| 2791 | gdImageStringLB(pGraph, gdFontSmall, | 
|---|
| 2792 | (int)(ptlOrigo.x - 3 - strlen(&szData[0])*6), | 
|---|
| 2793 | (int)(ptlOrigo.y + 8/2 + 2), | 
|---|
| 2794 | &szData[0], clrForeground); | 
|---|
| 2795 | sprintf(&szData[0], "%1.*f", rdMax > 10 ? 0 : 1, rdMax); | 
|---|
| 2796 | gdImageStringLB(pGraph, gdFontSmall, | 
|---|
| 2797 | (int)(ptlOrigo.x - 3 - strlen(&szData[0])*6), | 
|---|
| 2798 | (int)(ptlYEnd.y + 8/2), | 
|---|
| 2799 | &szData[0], clrForeground); | 
|---|
| 2800 |  | 
|---|
| 2801 | rd    = 14 + 10;                               //length of on scale tag | 
|---|
| 2802 | cTags = (int)((ptlYEnd.y - ptlOrigo.y) / rd);  //max number of tags | 
|---|
| 2803 | if (cTags > 0) | 
|---|
| 2804 | { | 
|---|
| 2805 | rdD = rdMax - rdMin; | 
|---|
| 2806 | if (rd > 10) | 
|---|
| 2807 | rdD = (int)(rdD/cTags); | 
|---|
| 2808 | else | 
|---|
| 2809 | rdD = ((int)(rdD/cTags*10))/10; | 
|---|
| 2810 | rd = rdMin + rdD; | 
|---|
| 2811 | while (rdD > 0.0 && (rd + rdD) <= rdMax) | 
|---|
| 2812 | { | 
|---|
| 2813 | int y = (int)(ptlOrigo.y + (ptlYEnd.y - ptlOrigo.y)/(rdMax-rdMin)*(rd - rdMin)); | 
|---|
| 2814 | sprintf(&szData[0], "%1.*f", rdMax > 10 ? 0 : 1, rd); | 
|---|
| 2815 | gdImageStringLB(pGraph, gdFontSmall, | 
|---|
| 2816 | (int)(ptlOrigo.x - 3 - strlen(&szData[0])*6), | 
|---|
| 2817 | y + 8/2, | 
|---|
| 2818 | &szData[0], clrForeground); | 
|---|
| 2819 | gdImageLineLB(pGraph, (int)(ptlOrigo.x - 1), y, (int)(ptlOrigo.x + 1), y, clrAxis); | 
|---|
| 2820 |  | 
|---|
| 2821 | /* next */ | 
|---|
| 2822 | rd += rdD; | 
|---|
| 2823 | } | 
|---|
| 2824 | } | 
|---|
| 2825 | } | 
|---|
| 2826 |  | 
|---|
| 2827 |  | 
|---|
| 2828 | /** | 
|---|
| 2829 | * Draw all lines. | 
|---|
| 2830 | */ | 
|---|
| 2831 | void    kGraph::drawLines(void)            throw(kError::enmErrors) | 
|---|
| 2832 | { | 
|---|
| 2833 | kGraphDataSet *pDataSet; | 
|---|
| 2834 |  | 
|---|
| 2835 | assert((int)enmTypeCd == (int)lines); | 
|---|
| 2836 |  | 
|---|
| 2837 | pDataSet = listDataSets.getFirst(); | 
|---|
| 2838 | while (pDataSet != NULL) | 
|---|
| 2839 | { | 
|---|
| 2840 | pDataSet->setColor(pGraph); | 
|---|
| 2841 | drawLine(pDataSet); | 
|---|
| 2842 |  | 
|---|
| 2843 | /* next */ | 
|---|
| 2844 | pDataSet = (kGraphDataSet *)pDataSet->getNext(); | 
|---|
| 2845 | } | 
|---|
| 2846 | } | 
|---|
| 2847 |  | 
|---|
| 2848 |  | 
|---|
| 2849 | /** | 
|---|
| 2850 | * Draws a line for the given data set. | 
|---|
| 2851 | * @param     pDataSet  Pointer to the dataset for the line. | 
|---|
| 2852 | * @remark    not implemented. | 
|---|
| 2853 | */ | 
|---|
| 2854 | void    kGraph::drawLine(const kGraphDataSet *pDataSet) throw(kError::enmErrors) | 
|---|
| 2855 | { | 
|---|
| 2856 | BOOL   fFirstTime = TRUE; | 
|---|
| 2857 | int    xPrev = 0; /* don't have to initialized, but it removes gcc warning (release) */ | 
|---|
| 2858 | int    yPrev = 0; /* don't have to initialized, but it removes gcc warning (release) */ | 
|---|
| 2859 | double rdMinX = minX(); | 
|---|
| 2860 | double rdMinY = minY(); | 
|---|
| 2861 | double rdDX = maxX() - rdMinX; | 
|---|
| 2862 | double rdDY = maxY() - rdMinY; | 
|---|
| 2863 |  | 
|---|
| 2864 | kGraphData *p = pDataSet->listData.getFirst(); | 
|---|
| 2865 |  | 
|---|
| 2866 | if (rdDX != 0.0 && rdDY != 0.0) | 
|---|
| 2867 | { | 
|---|
| 2868 | while (p != NULL) | 
|---|
| 2869 | { | 
|---|
| 2870 | int x, y; | 
|---|
| 2871 |  | 
|---|
| 2872 | x = (int)(ptlOrigo.x + ((ptlXEnd.x - ptlOrigo.x)/rdDX * (p->rdX - rdMinX))); | 
|---|
| 2873 | y = (int)(ptlOrigo.y + ((ptlYEnd.y - ptlOrigo.y)/rdDY * (p->rdY - rdMinY))); | 
|---|
| 2874 | if (fFirstTime) | 
|---|
| 2875 | { | 
|---|
| 2876 | xPrev = x; | 
|---|
| 2877 | yPrev = y; | 
|---|
| 2878 | fFirstTime = FALSE; | 
|---|
| 2879 | } | 
|---|
| 2880 | gdImageLineLB(pGraph, xPrev, yPrev, x, y, pDataSet->getColor()); | 
|---|
| 2881 |  | 
|---|
| 2882 | /* next */ | 
|---|
| 2883 | p = (kGraphData*)p->getNext(); | 
|---|
| 2884 | xPrev = x; | 
|---|
| 2885 | yPrev = y; | 
|---|
| 2886 | } | 
|---|
| 2887 | } | 
|---|
| 2888 | } | 
|---|
| 2889 |  | 
|---|
| 2890 |  | 
|---|
| 2891 | /** | 
|---|
| 2892 | * Draws the legend. | 
|---|
| 2893 | * @remark    not implemented. | 
|---|
| 2894 | */ | 
|---|
| 2895 | void kGraph::drawLegend(void)  throw(kError::enmErrors) | 
|---|
| 2896 | { | 
|---|
| 2897 | if (fLegend == FALSE) | 
|---|
| 2898 | return; | 
|---|
| 2899 |  | 
|---|
| 2900 | /* TODO */ | 
|---|
| 2901 | } | 
|---|
| 2902 |  | 
|---|
| 2903 |  | 
|---|
| 2904 | /** | 
|---|
| 2905 | * Converts an ISO date to days. | 
|---|
| 2906 | * @returns   Returns days after Christ, year 0. | 
|---|
| 2907 | * @param     pszDate  Pointer to ISO date string. | 
|---|
| 2908 | * @remark    pszDate should be an ISO date, if not an exception may occur. | 
|---|
| 2909 | *            Use isDate to check it is an ISO date. | 
|---|
| 2910 | */ | 
|---|
| 2911 | double kGraph::dateToDbl(const char *pszDate) | 
|---|
| 2912 | { | 
|---|
| 2913 | double rdRet = dbDateToDaysAfterChrist(pszDate); | 
|---|
| 2914 | return rdRet != -1 ? rdRet : _NAN; | 
|---|
| 2915 | } | 
|---|
| 2916 |  | 
|---|
| 2917 |  | 
|---|
| 2918 | /** | 
|---|
| 2919 | * Converts days to an ISO date. | 
|---|
| 2920 | * @returns   Success indicator. TRUE / FALSE. | 
|---|
| 2921 | * @param     rdDate   Date in double, (really days from year 0). | 
|---|
| 2922 | * @param     pszDate  Pointer to result buffer. Will hold ISO date string on successful return. | 
|---|
| 2923 | */ | 
|---|
| 2924 | BOOL kGraph::dblToDate(double rdDate, char *pszDate) | 
|---|
| 2925 | { | 
|---|
| 2926 | if (rdDate != rdDate) | 
|---|
| 2927 | return FALSE; | 
|---|
| 2928 | return dbDaysAfterChristToDate((signed long)rdDate, pszDate); | 
|---|
| 2929 | } | 
|---|
| 2930 |  | 
|---|
| 2931 |  | 
|---|
| 2932 | /** | 
|---|
| 2933 | * Checks if the given text string is an ISO date. | 
|---|
| 2934 | * @returns   TRUE - if date, else FALSE. | 
|---|
| 2935 | * @param     pszDate  Possible ISO date string. | 
|---|
| 2936 | */ | 
|---|
| 2937 | BOOL kGraph::isDate(const char *pszDate) | 
|---|
| 2938 | { | 
|---|
| 2939 | return strlen(pszDate) == 10 && pszDate[4] == '-' && pszDate[7] == '-'; | 
|---|
| 2940 | } | 
|---|
| 2941 |  | 
|---|
| 2942 |  | 
|---|
| 2943 | /** | 
|---|
| 2944 | * frees all storage. | 
|---|
| 2945 | * @remark    Called only at destruction. (That is destructor or when contruction failes.) | 
|---|
| 2946 | */ | 
|---|
| 2947 | void kGraph::destroy(void) | 
|---|
| 2948 | { | 
|---|
| 2949 | if (pGraph != NULL)         gdImageDestroy(pGraph); | 
|---|
| 2950 | if (pszFilename != NULL)    delete pszFilename; | 
|---|
| 2951 | if (pszTitle != NULL)       delete pszTitle; | 
|---|
| 2952 | if (pszTitleX != NULL)      delete pszTitleX; | 
|---|
| 2953 | if (pszTitleY != NULL)      delete pszTitleY; | 
|---|
| 2954 | if (pszBackground != NULL)  delete pszBackground; | 
|---|
| 2955 | } | 
|---|
| 2956 |  | 
|---|
| 2957 |  | 
|---|
| 2958 | /** | 
|---|
| 2959 | * Adds a warning to the list of warnings. | 
|---|
| 2960 | * @param     enmErrorCd  Warning code. | 
|---|
| 2961 | */ | 
|---|
| 2962 | void   kGraph::addWarning(kError::enmErrors enmErrorCd) | 
|---|
| 2963 | { | 
|---|
| 2964 | listWarnings.insert(new kWarningEntry(enmErrorCd)); | 
|---|
| 2965 | } | 
|---|
| 2966 |  | 
|---|
| 2967 |  | 
|---|
| 2968 | /** | 
|---|
| 2969 | * Finds the max X value in all data sets. | 
|---|
| 2970 | * @returns   max X value. 0.0 if no sets | 
|---|
| 2971 | */ | 
|---|
| 2972 | double kGraph::maxX(void) | 
|---|
| 2973 | { | 
|---|
| 2974 | if (rdMaxX != rdMaxX) | 
|---|
| 2975 | { | 
|---|
| 2976 | /* first time */ | 
|---|
| 2977 | if (rdEndX != rdEndX) | 
|---|
| 2978 | {   /* not spesified by user */ | 
|---|
| 2979 | kGraphDataSet *p = listDataSets.getFirst(); | 
|---|
| 2980 |  | 
|---|
| 2981 | while (p != NULL) | 
|---|
| 2982 | { | 
|---|
| 2983 | double rd = p->maxX(); | 
|---|
| 2984 | if (rdMaxX < rd || rdMaxX != rdMaxX) | 
|---|
| 2985 | rdMaxX = rd; | 
|---|
| 2986 | p = (kGraphDataSet*)p->getNext(); | 
|---|
| 2987 | } | 
|---|
| 2988 |  | 
|---|
| 2989 | rdMaxX = rdMaxX == rdMaxX ? rdMaxX : 0.0; | 
|---|
| 2990 | } | 
|---|
| 2991 | else /* spesified by user */ | 
|---|
| 2992 | rdMaxX = rdEndX; | 
|---|
| 2993 | } | 
|---|
| 2994 |  | 
|---|
| 2995 | return rdMaxX; | 
|---|
| 2996 | } | 
|---|
| 2997 |  | 
|---|
| 2998 |  | 
|---|
| 2999 | /** | 
|---|
| 3000 | * Finds the min X value in all data sets. | 
|---|
| 3001 | * @returns   min X value. 0.0 if no sets | 
|---|
| 3002 | * @remark    Addjusts value if close to 0. | 
|---|
| 3003 | */ | 
|---|
| 3004 | double kGraph::minX(void) | 
|---|
| 3005 | { | 
|---|
| 3006 | if (rdMinX != rdMinX) | 
|---|
| 3007 | { | 
|---|
| 3008 | /* first time */ | 
|---|
| 3009 | if (rdStartX != rdStartX) | 
|---|
| 3010 | {   /* not spesified by user */ | 
|---|
| 3011 | kGraphDataSet *p = listDataSets.getFirst(); | 
|---|
| 3012 |  | 
|---|
| 3013 | while (p != NULL) | 
|---|
| 3014 | { | 
|---|
| 3015 | double rd = p->minX(); | 
|---|
| 3016 | if (rdMinX > rd || rdMinX != rdMinX) | 
|---|
| 3017 | rdMinX = rd; | 
|---|
| 3018 | p = (kGraphDataSet*)p->getNext(); | 
|---|
| 3019 | } | 
|---|
| 3020 |  | 
|---|
| 3021 | /* addjustment */ | 
|---|
| 3022 | if (rdMinX != rdMinX) | 
|---|
| 3023 | rdMinX = fXDate ? maxX() - 1.0 : 0.0; | 
|---|
| 3024 | else if (rdMinX >= 0.0) | 
|---|
| 3025 | rdMinX = fXDate ? rdMinX : 0.0; | 
|---|
| 3026 | else | 
|---|
| 3027 | { | 
|---|
| 3028 | /* TODO negative values are not supported yet. */ | 
|---|
| 3029 | addWarning(kError::warning_negative_values_are_not_supported_yet); | 
|---|
| 3030 | rdMinX = 0.0; | 
|---|
| 3031 | } | 
|---|
| 3032 | } | 
|---|
| 3033 | else /* spesified by user */ | 
|---|
| 3034 | rdMinX = rdStartX; | 
|---|
| 3035 | } | 
|---|
| 3036 |  | 
|---|
| 3037 | return rdMinX; | 
|---|
| 3038 | } | 
|---|
| 3039 |  | 
|---|
| 3040 |  | 
|---|
| 3041 | /** | 
|---|
| 3042 | * Finds the max Y value in all data sets. | 
|---|
| 3043 | * @returns   max Y value. 0.0 if no sets | 
|---|
| 3044 | */ | 
|---|
| 3045 | double kGraph::maxY(void) | 
|---|
| 3046 | { | 
|---|
| 3047 | if (rdMaxY != rdMaxY) | 
|---|
| 3048 | { | 
|---|
| 3049 | /* first time */ | 
|---|
| 3050 | if (rdEndY != rdEndY) | 
|---|
| 3051 | {   /* not spesified by user */ | 
|---|
| 3052 | kGraphDataSet *p = listDataSets.getFirst(); | 
|---|
| 3053 |  | 
|---|
| 3054 | while (p != NULL) | 
|---|
| 3055 | { | 
|---|
| 3056 | double rd = p->maxY(); | 
|---|
| 3057 | if (rdMaxY < rd || rdMaxY != rdMaxY) | 
|---|
| 3058 | rdMaxY = rd; | 
|---|
| 3059 | p = (kGraphDataSet*)p->getNext(); | 
|---|
| 3060 | } | 
|---|
| 3061 |  | 
|---|
| 3062 | rdMaxY = rdMaxY == rdMaxY ? rdMaxY : 0.0; | 
|---|
| 3063 | } | 
|---|
| 3064 | else /* spesified by user */ | 
|---|
| 3065 | rdMaxY = rdEndY; | 
|---|
| 3066 | } | 
|---|
| 3067 |  | 
|---|
| 3068 | return rdMaxY; | 
|---|
| 3069 | } | 
|---|
| 3070 |  | 
|---|
| 3071 |  | 
|---|
| 3072 | /** | 
|---|
| 3073 | * Finds the min Y value in all data sets. | 
|---|
| 3074 | * @returns   min Y value. 0.0 if no sets | 
|---|
| 3075 | * @remark    Addjusts value if close to 0. | 
|---|
| 3076 | */ | 
|---|
| 3077 | double kGraph::minY(void) | 
|---|
| 3078 | { | 
|---|
| 3079 | if (rdMinY != rdMinY) | 
|---|
| 3080 | { | 
|---|
| 3081 | /* first time */ | 
|---|
| 3082 | if (rdStartY != rdStartY) | 
|---|
| 3083 | {   /* not spesified by user */ | 
|---|
| 3084 | kGraphDataSet *p = listDataSets.getFirst(); | 
|---|
| 3085 |  | 
|---|
| 3086 | while (p != NULL) | 
|---|
| 3087 | { | 
|---|
| 3088 | double rd = p->minY(); | 
|---|
| 3089 | if (rdMinY > rd || rdMinY != rdMinY) | 
|---|
| 3090 | rdMinY = rd; | 
|---|
| 3091 | p = (kGraphDataSet*)p->getNext(); | 
|---|
| 3092 | } | 
|---|
| 3093 |  | 
|---|
| 3094 | /* addjustment */ | 
|---|
| 3095 | if (rdMinY != rdMinY) | 
|---|
| 3096 | rdMinY = 0.0; | 
|---|
| 3097 | else if (rdMinY >= 0.0) | 
|---|
| 3098 | rdMinY = 0.0; | 
|---|
| 3099 | else | 
|---|
| 3100 | {   /* TODO negative values are not supported yet. */ | 
|---|
| 3101 | addWarning(kError::warning_negative_values_are_not_supported_yet); | 
|---|
| 3102 | rdMinY = 0.0; | 
|---|
| 3103 | } | 
|---|
| 3104 | } | 
|---|
| 3105 | else /* spesified by user */ | 
|---|
| 3106 | rdMinY = rdStartY; | 
|---|
| 3107 | } | 
|---|
| 3108 |  | 
|---|
| 3109 | return rdMinY; | 
|---|
| 3110 | } | 
|---|
| 3111 |  | 
|---|
| 3112 |  | 
|---|
| 3113 | /** | 
|---|
| 3114 | * Reads a color parameter. | 
|---|
| 3115 | * @returns   24Bit RGB color value. | 
|---|
| 3116 | * @param     pszColor  Pointer to color string. That is "#RRGGBB". | 
|---|
| 3117 | */ | 
|---|
| 3118 | unsigned long   kGraph::readColor(const char *pszColor) | 
|---|
| 3119 | { | 
|---|
| 3120 | unsigned long ulColor = 0xffffff; | 
|---|
| 3121 |  | 
|---|
| 3122 | if (*pszColor == '#') | 
|---|
| 3123 | { | 
|---|
| 3124 | ulColor = 0; | 
|---|
| 3125 | for (int i = 1; i < 7; i++) | 
|---|
| 3126 | { | 
|---|
| 3127 | ulColor = ulColor << 4; | 
|---|
| 3128 | if (pszColor[i] >= '0' && pszColor[i] <= '9') | 
|---|
| 3129 | ulColor |= pszColor[i] - '0'; | 
|---|
| 3130 | else if (pszColor[i] >= 'A' && pszColor[i] <= 'F') | 
|---|
| 3131 | ulColor |= pszColor[i] - 'A' + 0xa; | 
|---|
| 3132 | else if (pszColor[i] >= 'a' && pszColor[i] <= 'f') | 
|---|
| 3133 | ulColor |= pszColor[i] - 'a' + 0xa; | 
|---|
| 3134 | else | 
|---|
| 3135 | addWarning(kError::warning_invalid_color_value); | 
|---|
| 3136 | } | 
|---|
| 3137 | } | 
|---|
| 3138 | else | 
|---|
| 3139 | addWarning(kError::warning_invalid_color_value); | 
|---|
| 3140 |  | 
|---|
| 3141 | return ulColor; | 
|---|
| 3142 | } | 
|---|
| 3143 |  | 
|---|
| 3144 |  | 
|---|
| 3145 | /** | 
|---|
| 3146 | * Allocates a color in the image. | 
|---|
| 3147 | * @returns   GifDraw Color. | 
|---|
| 3148 | * @param     ulColor  24Bit RGB color value. | 
|---|
| 3149 | */ | 
|---|
| 3150 | int kGraph::setColor(unsigned long ulColor) | 
|---|
| 3151 | { | 
|---|
| 3152 | return gdImageColorAllocate(pGraph, | 
|---|
| 3153 | (int)(0xFF & (ulColor >> 16)), | 
|---|
| 3154 | (int)(0xFF & (ulColor >> 8)), | 
|---|
| 3155 | (int)(0xFF & ulColor)); | 
|---|
| 3156 | } | 
|---|
| 3157 |  | 
|---|
| 3158 |  | 
|---|
| 3159 | /** | 
|---|
| 3160 | * Allocates/sets default colors. | 
|---|
| 3161 | */ | 
|---|
| 3162 | void kGraph::setColors(void) | 
|---|
| 3163 | { | 
|---|
| 3164 | clrBackground = setColor(ulBGColor != ~0UL ? ulBGColor : 0x00000000UL); /* vitally important that this is done first! */ | 
|---|
| 3165 | clrForeground = setColor(ulFGColor != ~0UL ? ulFGColor : 0x0000FF00UL); | 
|---|
| 3166 | clrAxis      = setColor(ulAxisColor != ~0UL ? ulAxisColor : 0x00808080UL); | 
|---|
| 3167 | } | 
|---|
| 3168 |  | 
|---|
| 3169 |  | 
|---|
| 3170 | /** | 
|---|
| 3171 | * Constructor. | 
|---|
| 3172 | * @remark    Throws kError::enmError on error. | 
|---|
| 3173 | */ | 
|---|
| 3174 | kGraph::kGraph(const kTag &tag, const char *pszBaseDir) throw(kError::enmErrors) | 
|---|
| 3175 | : pGraph(NULL), enmTypeCd(unknown), enmSubTypeCd(normal), | 
|---|
| 3176 | pszFilename(NULL), pszTitle(NULL), pszTitleX(NULL), | 
|---|
| 3177 | pszTitleY(NULL), pszBackground(NULL), fLegend(FALSE), | 
|---|
| 3178 | cX(~0L), cY(~0L), | 
|---|
| 3179 | rdStartX(_NAN), rdEndX(_NAN), rdStartY(_NAN), rdEndY(_NAN), | 
|---|
| 3180 | fXDate(FALSE), | 
|---|
| 3181 | ulBGColor(~0UL), ulFGColor(~0UL), ulAxisColor(~0UL), | 
|---|
| 3182 | rdMaxX(_NAN), rdMinX(_NAN), rdMaxY(_NAN), rdMinY(_NAN) | 
|---|
| 3183 | { | 
|---|
| 3184 | try | 
|---|
| 3185 | { | 
|---|
| 3186 | analyseTag(tag, pszBaseDir); | 
|---|
| 3187 | createBaseGraph(); | 
|---|
| 3188 | if (fLegend) | 
|---|
| 3189 | drawLegend(); | 
|---|
| 3190 | drawLines(); | 
|---|
| 3191 | } | 
|---|
| 3192 | catch (kError::enmErrors enmErrorCd) | 
|---|
| 3193 | { | 
|---|
| 3194 | destroy(); | 
|---|
| 3195 | throw(enmErrorCd); | 
|---|
| 3196 | } | 
|---|
| 3197 | } | 
|---|
| 3198 |  | 
|---|
| 3199 |  | 
|---|
| 3200 | /** | 
|---|
| 3201 | * Destructor. | 
|---|
| 3202 | * @remark    calls destroy(). | 
|---|
| 3203 | */ | 
|---|
| 3204 | kGraph::~kGraph(void) | 
|---|
| 3205 | { | 
|---|
| 3206 | destroy(); | 
|---|
| 3207 | } | 
|---|
| 3208 |  | 
|---|
| 3209 |  | 
|---|
| 3210 | /** | 
|---|
| 3211 | * Saves the graph to the filename specified in the tag. | 
|---|
| 3212 | * 2 | 
|---|
| 3213 | * @returns   Errorcode. | 
|---|
| 3214 | */ | 
|---|
| 3215 | kError::enmErrors kGraph::save(void) | 
|---|
| 3216 | { | 
|---|
| 3217 | FILE *phFileOut; | 
|---|
| 3218 |  | 
|---|
| 3219 | assert(pGraph != NULL); | 
|---|
| 3220 | assert(pszFilename != NULL); | 
|---|
| 3221 |  | 
|---|
| 3222 | phFileOut = fopen(pszFilename, "wb"); | 
|---|
| 3223 | if (phFileOut != NULL) | 
|---|
| 3224 | { | 
|---|
| 3225 | gdImageGif(pGraph, phFileOut); | 
|---|
| 3226 | fclose(phFileOut); | 
|---|
| 3227 | } | 
|---|
| 3228 | else | 
|---|
| 3229 | return kError::error_opening_output_file; | 
|---|
| 3230 | return kError::no_error; | 
|---|
| 3231 | } | 
|---|
| 3232 |  | 
|---|
| 3233 |  | 
|---|
| 3234 | /** | 
|---|
| 3235 | * Prints warnings. | 
|---|
| 3236 | * @returns   Number of warnings. | 
|---|
| 3237 | * @param     phLog  Pointer to log file handle. | 
|---|
| 3238 | */ | 
|---|
| 3239 | unsigned long kGraph::showWarnings(FILE *phLog, const kFileEntry *pCurFile) | 
|---|
| 3240 | { | 
|---|
| 3241 | unsigned long cWarnings = 0; | 
|---|
| 3242 | kWarningEntry *p = listWarnings.getFirst(); | 
|---|
| 3243 |  | 
|---|
| 3244 | while (p != NULL) | 
|---|
| 3245 | { | 
|---|
| 3246 | cWarnings++; | 
|---|
| 3247 | fprintf(phLog, "%s(%ld) : warning: kGraph - %s\n", | 
|---|
| 3248 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, | 
|---|
| 3249 | kError::queryDescription(p->getWarningCode())); | 
|---|
| 3250 | p = (kWarningEntry*)p->getNext(); | 
|---|
| 3251 | } | 
|---|
| 3252 |  | 
|---|
| 3253 | return cWarnings; | 
|---|
| 3254 | } | 
|---|
| 3255 |  | 
|---|
| 3256 |  | 
|---|
| 3257 | /* include template code */ | 
|---|
| 3258 | #include "kLIFO.cpp" | 
|---|
| 3259 | #include "kList.cpp" | 
|---|
| 3260 |  | 
|---|
| 3261 | #ifdef __EMX__ | 
|---|
| 3262 | template class kLIFO<kSqlEntry>; | 
|---|
| 3263 | #endif | 
|---|
| 3264 |  | 
|---|