home *** CD-ROM | disk | FTP | other *** search
/ Borland Programmer's Resource / Borland_Programmers_Resource_CD_1995.iso / code / wxwin140 / src / wx_utils.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-19  |  13.1 KB  |  726 lines

  1. /*
  2.  * File:     wx_utils.cc
  3.  * Purpose:  Various utilities
  4.  *
  5.  *                       wxWindows 1.40
  6.  * Copyright (c) 1993 Artificial Intelligence Applications Institute,
  7.  *                   The University of Edinburgh
  8.  *
  9.  *                     Author: Julian Smart
  10.  *                       Date: 18-4-93
  11.  *
  12.  * Permission to use, copy, modify, and distribute this software and its
  13.  * documentation for any purpose is hereby granted without fee, provided
  14.  * that the above copyright notice, author statement and this permission
  15.  * notice appear in all copies of this software and related documentation.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS,
  18.  * IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
  19.  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  20.  *
  21.  * IN NO EVENT SHALL THE ARTIFICIAL INTELLIGENCE APPLICATIONS INSTITUTE OR THE
  22.  * UNIVERSITY OF EDINBURGH BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR
  23.  * CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM
  24.  * LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF
  25.  * DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH
  26.  * THE USE OR PERFORMANCE OF THIS SOFTWARE.
  27.  */
  28.  
  29. #include <windows.h>
  30. #include <iostream.h>
  31. #include <fstream.h>
  32. #include <ctype.h>
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <errno.h>
  37. #include "common.h"
  38.  
  39. #include "wx_utils.h"
  40.  
  41. #ifdef wx_x
  42. #include <sys/types.h>
  43. #include <sys/time.h>
  44. #include <sys/syscall.h>
  45. #include <signal.h>
  46. #include <tiuser.h>
  47. extern "C" int select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
  48. #endif
  49.  
  50. // Useful buffer
  51. char wxBuffer[1000];
  52.  
  53. char *copystring(char *s)
  54. {
  55.   int l = strlen(s);
  56.   char *news = new char[l+1];
  57.   strcpy(news, s);
  58.   return news;
  59. }
  60.  
  61. #ifdef DEBUG
  62. wxLogClass::wxLogClass(char *file)
  63. {
  64.   log_file = copystring(file);
  65.   the_stream = new ofstream(log_file);
  66.   delete the_stream;
  67. }
  68.  
  69. wxLogClass::~wxLogClass()
  70. {
  71.   delete log_file;
  72. }
  73.  
  74. void wxLogClass::Open(void)
  75. {
  76.   the_stream = new ofstream(log_file, ios::app);
  77. }
  78.  
  79. void wxLogClass::Close(void)
  80. {
  81.   delete the_stream;
  82. }
  83.  
  84. wxLogClass& wxLogClass::operator << (char *s)
  85. {
  86.   this->Open();
  87.   *the_stream << s;
  88.   the_stream->flush();
  89.   this->Close();
  90.   return *this;
  91. }
  92.  
  93. wxLogClass& wxLogClass::operator << (int i)
  94. {
  95.   this->Open();
  96.   *the_stream << i;
  97.   the_stream->flush();
  98.   this->Close();
  99.   return *this;
  100. }
  101.  
  102. wxLogClass& wxLogClass::operator << (double i)
  103. {
  104.   this->Open();
  105.   *the_stream << i;
  106.   the_stream->flush();
  107.   this->Close();
  108.   return *this;
  109. }
  110.  
  111. wxLogClass wxLog("log");
  112. #endif
  113.  
  114. // Id generation
  115. static long wxCurrentId = 100;
  116. long NewId(void)
  117. {
  118.   return wxCurrentId++;
  119. }
  120.  
  121. void RegisterId(long id)
  122. {
  123.   if (id > wxCurrentId)
  124.     wxCurrentId = id + 1;
  125. }
  126.  
  127.  
  128. void StringToFloat(char *s, float *number)
  129. {
  130.   if (s && strlen(s) > 0)
  131.   {
  132.     double n = strtod(s, NULL);
  133.     *number = (float)n;
  134.   }
  135. }
  136.  
  137. void StringToDouble(char *s, double *number)
  138. {
  139.   if (s && strlen(s) > 0)
  140.   {
  141.     *number = strtod(s, NULL);
  142.   }
  143. }
  144.  
  145. char *FloatToString(float number)
  146. {
  147.   char buf[80];
  148.   sprintf(buf, "%.2f", number);
  149.   return copystring(buf);
  150. }
  151.  
  152. char *DoubleToString(double number)
  153. {
  154.   char buf[80];
  155.   sprintf(buf, "%.2lf", number);
  156.   return copystring(buf);
  157. }
  158.  
  159. void StringToInt(char *s, int *number)
  160. {
  161.   if (s && strlen(s) > 0)
  162.   {
  163.     long n = strtol(s, NULL, 10);
  164.     *number = (int)n;
  165.   }
  166. }
  167.  
  168. void StringToLong(char *s, long *number)
  169. {
  170.   if (s && strlen(s) > 0)
  171.   {
  172.     *number = strtol(s, NULL, 10);
  173.   }
  174. }
  175.  
  176. char *IntToString(int number)
  177. {
  178.   char buf[80];
  179.   sprintf(buf, "%d", number);
  180.   return copystring(buf);
  181. }
  182.  
  183. char *LongToString(long number)
  184. {
  185.   char buf[80];
  186.   sprintf(buf, "%ld", number);
  187.   return copystring(buf);
  188. }
  189.  
  190. // Match a string (one) within a string (two)
  191. Bool StringMatch(char *one, char *two)
  192. {
  193.   
  194.   int i = 0;
  195.   int len = strlen(two);
  196.   int len_one = strlen(one);
  197.   int found = FALSE;
  198.   while (!found && i < len)
  199.   {
  200.     strncpy(wxBuffer, two + i, len_one);
  201.     wxBuffer[len_one] = 0;
  202.     if (strcmp(one, wxBuffer) == 0)
  203.       found = TRUE;
  204.     i ++;
  205.   }
  206.   return found;
  207. }
  208.  
  209.  
  210. /****** FILE UTILITIES ******/
  211.  
  212. void wxPathList::Add(char *path)
  213. {
  214.   Append((wxObject *)path);
  215. }
  216.  
  217. // Add paths e.g. from the PATH environment variable
  218. void wxPathList::AddEnvList(char *envVariable)
  219. {
  220.   char *val = getenv(envVariable);
  221.   if (val)
  222.   {
  223.     char *s = copystring(val);
  224.     char *token = strtok(s, " :;");
  225.     if (token)
  226.     {
  227.       Add(copystring(token));
  228.       while (token)
  229.       {
  230.         token = strtok(NULL, " :;");
  231.         if (token)
  232.           Add(copystring(token));
  233.       }
  234.     }
  235.   }
  236. }
  237.  
  238. // Given a full filename (with path), ensure that that file can
  239. // be accessed again USING FILENAME ONLY by adding the path
  240. // to the list if not already there.
  241. void wxPathList::EnsureFileAccessible(char *path)
  242. {
  243.   char *path_only = PathOnly(path);
  244.   if (path_only)
  245.   {
  246.     if (!Member(path_only))
  247.       Add(path_only);
  248.     else delete path_only;
  249.   }
  250. }
  251.  
  252. Bool wxPathList::Member(char *path)
  253. {
  254.   char *pathcopy = copystring(path);
  255.   int i;
  256.   for (i = 0; i < (int)strlen(pathcopy); i++)
  257.     pathcopy[i] = toupper(pathcopy[i]);
  258.  
  259.   wxNode *node = First();
  260.   Bool found = FALSE;
  261.   while (node && !found)
  262.   {
  263.     char *path = (char *)node->Data();
  264.     
  265.     strcpy(wxBuffer, path);
  266.  
  267.     for (i = 0; i < (int)strlen(wxBuffer); i++)
  268.       wxBuffer[i] = toupper(wxBuffer[i]);
  269.  
  270.     if (strcmp(pathcopy, wxBuffer) == 0)
  271.     {
  272.       found = TRUE;
  273.       node = NULL;
  274.     }
  275.     else node = node->Next();
  276.   }
  277.   delete pathcopy;
  278.   return found;
  279. }
  280.  
  281. char *wxPathList::FindValidPath(char *file)
  282. {
  283.   if (FileExists(file))
  284.     return file;
  285.  
  286.   char *filename;
  287.  
  288.   if (IsAbsolutePath(file))
  289.     filename = FileNameFromPath(file);
  290.   else
  291.     filename = copystring(file);
  292.  
  293.   wxNode *node = First();
  294.   char *found = NULL;
  295.   while (node && !found)
  296.   {
  297.     char *path = (char *)node->Data();
  298.     strcpy(wxBuffer, path);
  299. #ifdef wx_x
  300.     strcat(wxBuffer, "/");
  301. #endif
  302. #ifdef wx_msw
  303.     strcat(wxBuffer, "\\");
  304. #endif
  305.     strcat(wxBuffer, filename);
  306. #ifdef wx_msw
  307.     Unix2DosFilename(wxBuffer);
  308. #endif
  309.     if (FileExists(wxBuffer))
  310.     {
  311.       found = wxBuffer;
  312.     }
  313.     else
  314.       node = node->Next();
  315.   }
  316.   delete filename;
  317.   return found;
  318. }
  319.  
  320. Bool FileExists(char *filename)
  321. {
  322.   if (!filename)
  323.     return FALSE;
  324.   FILE *fd = fopen(filename, "r");
  325.   Bool bad = (fd == NULL);
  326.   if (fd)
  327.     fclose(fd);
  328.  
  329.   return !bad;
  330. }
  331.  
  332. Bool IsAbsolutePath(char *filename)
  333. {
  334.   int len = strlen(filename);
  335.   if ((len > 0 && (filename[0] == '/' || filename[0] == '\\')) ||
  336.       (len > 1 && (filename[1] == ':')))
  337.     return TRUE;
  338.   else
  339.     return FALSE;
  340. }
  341.  
  342. // Return just the filename, not the path
  343. char *FileNameFromPath(char *path)
  344. {
  345.   if (!path)
  346.     return NULL;
  347.  
  348.   char buf[200];
  349.   int i = 0;
  350.   int l = strlen(path);
  351.   Bool done = FALSE;
  352.  
  353.   i = l - 1;
  354.  
  355.   // Search backward for a backward or forward slash
  356.   while (!done && i > -1)
  357.   {
  358.     if (path[i] == '/' || path[i] == '\\')
  359.     {
  360.       done = TRUE;
  361.     }
  362.     else i --;
  363.   }
  364.   i ++;
  365.  
  366.   int j;
  367.   for (j = i; j < l; j++)
  368.   {
  369.     buf[j - i] = path[j];
  370.   }
  371.   buf[j - i] = 0;
  372.   return copystring(buf);
  373. }
  374.  
  375. // Return just the directory, or NULL if no directort
  376. char *PathOnly(char *path)
  377. {
  378.   if (!path)
  379.     return NULL;
  380.  
  381.   char buf[200];
  382.   strcpy(buf, path);
  383.  
  384.   int i = 0;
  385.   int l = strlen(path);
  386.   Bool done = FALSE;
  387.  
  388.   i = l - 1;
  389.  
  390.   // Search backward for a backward or forward slash
  391.   while (!done && i > -1)
  392.   {
  393.     if (path[i] == '/' || path[i] == '\\')
  394.     {
  395.       done = TRUE;
  396.     }
  397.     else i --;
  398.   }
  399.  
  400.   if (i >= 0)
  401.     buf[i] = 0;
  402.   else
  403.     buf[0] = 0;
  404.  
  405.   if (i <= 0)
  406.     return NULL;
  407.   else
  408.     return copystring(buf);
  409. }
  410.  
  411. // Utility for converting delimiters in DOS filenames to UNIX style
  412. // and back again - or we get nasty problems with delimiters
  413.  
  414. void Dos2UnixFilename(char *s)
  415. {
  416.   int l = strlen(s);
  417.   int i;
  418.   for (i = 0; i < l; i++)
  419.     if (s[i] == '\\')
  420.       s[i] = '/';
  421. }
  422.  
  423. void Unix2DosFilename(char *s)
  424. {
  425. #ifdef wx_msw
  426.   int l = strlen(s);
  427.   int i;
  428.   for (i = 0; i < l; i++)
  429.     if (s[i] == '/')
  430.       s[i] = '\\';
  431. #endif
  432. }
  433.  
  434. /*
  435.  * Check whether the filename has wildcards
  436.  *
  437.  */
  438.  
  439. Bool wxIsWild(char *pattern)
  440. {
  441.   register char *p = pattern;
  442.   register char c;
  443.  
  444.   while ((c = *p++) != '\0')
  445.     switch (c)
  446.       {
  447.       case '?':
  448.       case '[':
  449.       case '*':
  450.     return TRUE;
  451.  
  452.       case '\\':
  453.     if (*p++ == '\0')
  454.       return FALSE;
  455.       }
  456.  
  457.   return FALSE;
  458. }
  459.  
  460. /* Match the pattern PATTERN against the string TEXT;
  461.    return 1 if it matches, 0 otherwise.
  462.  
  463.    A match means the entire string TEXT is used up in matching.
  464.  
  465.    In the pattern string, `*' matches any sequence of characters,
  466.    `?' matches any character, [SET] matches any character in the specified set,
  467.    [!SET] matches any character not in the specified set.
  468.  
  469.    A set is composed of characters or ranges; a range looks like
  470.    character hyphen character (as in 0-9 or A-Z).
  471.    [0-9a-zA-Z_] is the set of characters allowed in C identifiers.
  472.    Any other character in the pattern must be matched exactly.
  473.  
  474.    To suppress the special syntactic significance of any of `[]*?!-\',
  475.    and match the character exactly, precede it with a `\'.
  476.  
  477.    If DOT_SPECIAL is nonzero,
  478.    `*' and `?' do not match `.' at the beginning of TEXT.
  479.  
  480.    THESE ROUTINES TAKEN FROM GLOB.C IN THE GNU LIBRARY. SEE GNU LICENSE.
  481.  */
  482.  
  483. static int
  484. wx_glob_match_after_star (char *pattern, char *text);
  485.  
  486. Bool wxMatchWild(char *pattern, char *text, Bool dot_special)
  487. {
  488.   register char *p = pattern, *t = text;
  489.   register char c;
  490.  
  491.   while ((c = *p++) != '\0')
  492.     switch (c)
  493.       {
  494.       case '?':
  495.     if (*t == '\0' || (dot_special && t == text && *t == '.'))
  496.       return 0;
  497.     else
  498.       ++t;
  499.     break;
  500.  
  501.       case '\\':
  502.     if (*p++ != *t++)
  503.       return 0;
  504.     break;
  505.  
  506.       case '*':
  507.     if (dot_special && t == text && *t == '.')
  508.       return 0;
  509.     return wx_glob_match_after_star (p, t);
  510.  
  511.       case '[':
  512.     {
  513.       register char c1 = *t++;
  514.       int invert;
  515.  
  516.       if (c1 == '\0')
  517.         return 0;
  518.  
  519.       invert = (*p == '!');
  520.  
  521.       if (invert)
  522.         p++;
  523.  
  524.       c = *p++;
  525.       while (1)
  526.         {
  527.           register char cstart = c, cend = c;
  528.  
  529.           if (c == '\\')
  530.         {
  531.           cstart = *p++;
  532.           cend = cstart;
  533.         }
  534.  
  535.           if (cstart == '\0')
  536.         return 0;    /* Missing ']'. */
  537.  
  538.           c = *p++;
  539.  
  540.           if (c == '-')
  541.         {
  542.           cend = *p++;
  543.           if (cend == '\\')
  544.             cend = *p++;
  545.           if (cend == '\0')
  546.             return 0;
  547.           c = *p++;
  548.         }
  549.           if (c1 >= cstart && c1 <= cend)
  550.         goto match;
  551.           if (c == ']')
  552.         break;
  553.         }
  554.       if (!invert)
  555.         return 0;
  556.       break;
  557.  
  558.     match:
  559.       /* Skip the rest of the [...] construct that already matched.  */
  560.       while (c != ']')
  561.         {
  562.           if (c == '\0')
  563.         return 0;
  564.           c = *p++;
  565.           if (c == '\0')
  566.         return 0;
  567.           if (c == '\\')
  568.         p++;
  569.         }
  570.       if (invert)
  571.         return 0;
  572.       break;
  573.     }
  574.  
  575.       default:
  576.     if (c != *t++)
  577.       return 0;
  578.       }
  579.  
  580.   return *t == '\0';
  581. }
  582.  
  583.  
  584. /* Like glob_match, but match PATTERN against any final segment of TEXT.  */
  585.  
  586. static Bool
  587. wx_glob_match_after_star (char *pattern, char *text)
  588. {
  589.   register char *p = pattern, *t = text;
  590.   register char c, c1;
  591.  
  592.   while ((c = *p++) == '?' || c == '*')
  593.     if (c == '?' && *t++ == '\0')
  594.       return 0;
  595.  
  596.   if (c == '\0')
  597.     return 1;
  598.  
  599.   if (c == '\\')
  600.     c1 = *p;
  601.   else
  602.     c1 = c;
  603.  
  604.   --p;
  605.   while (1)
  606.     {
  607.       if ((c == '[' || *t == c1) && wxMatchWild (p, t, 0))
  608.     return 1;
  609.       if (*t++ == '\0')
  610.     return 0;
  611.     }
  612. }
  613.  
  614. // Execute a command (e.g. another program) in a
  615. // system-independent manner.
  616. // Well - not quite. Note that under UNIX, the call will only
  617. // return immediately if an ampersand is appended to the command.
  618. // Under Windows, the call returns immediately.
  619. Bool wxExecute(char *command)
  620. {
  621. #ifdef wx_x
  622.   system(command);
  623.   return TRUE;
  624. #endif
  625. #ifdef wx_msw
  626.   int error = WinExec(command, SW_SHOW);
  627.   if (error >= 32)
  628.     return TRUE;
  629.   else
  630.     return FALSE;
  631. #endif
  632. }
  633.  
  634. // Concatenate two files to form third
  635. Bool wxConcatFiles(char *file1, char *file2, char *file3)
  636. {
  637.   FILE *fd1 = fopen(file1, "r");
  638.   FILE *fd2 = fopen(file2, "r");
  639.   FILE *fd3 = fopen(file3, "w");
  640.  
  641.   if (!(fd1 && fd2 && fd3))
  642.     return FALSE;
  643.  
  644.   int ch = -2;
  645.   while (ch != EOF)
  646.   {
  647.     ch = getc(fd1);
  648.     if (ch != EOF)
  649.       putc(ch, fd3);
  650.   }
  651.   ch = -2;
  652.   while (ch != EOF)
  653.   {
  654.     ch = getc(fd2);
  655.     if (ch != EOF)
  656.       putc(ch, fd3);
  657.   }
  658.   fclose(fd1);
  659.   fclose(fd2);
  660.   fclose(fd3);
  661.  
  662.   return TRUE;
  663. }
  664.  
  665. // Copy files
  666. Bool wxCopyFile(char *file1, char *file2)
  667. {
  668.   FILE *fd1 = fopen(file1, "r");
  669.   FILE *fd2 = fopen(file2, "w");
  670.  
  671.   if (!(fd1 && fd2))
  672.     return FALSE;
  673.  
  674.   int ch = -2;
  675.   while (ch != EOF)
  676.   {
  677.     ch = getc(fd1);
  678.     if (ch != EOF)
  679.       putc(ch, fd2);
  680.   }
  681.   fclose(fd1);
  682.   fclose(fd2);
  683.   return TRUE;
  684. }
  685.  
  686. Bool wxRemoveFile(char *file)
  687. {
  688. #ifdef wx_msw
  689.   int flag = remove(file);
  690. #endif
  691. #ifdef wx_x
  692.   int flag = unlink(file);
  693. #endif
  694.   if (flag == 0) return TRUE;
  695.   return FALSE;
  696. }
  697.  
  698. Bool wxRenameFile(char *file1, char *file2)
  699. {
  700.   int flag = rename(file1, file2);
  701.   if (flag == 0) return TRUE;
  702.   return FALSE;
  703. }
  704.  
  705. // Sleep for nSecs seconds under UNIX, do nothing under Windows
  706. // XView implementation according to the Heller manual
  707. void wxSleep(int nSecs)
  708. {
  709. #ifdef wx_x
  710.   int oldmask, mask;
  711.   struct timeval tv;
  712.  
  713.   tv.tv_sec = nSecs;
  714.   tv.tv_usec = 0;
  715.  
  716.   mask = sigmask(SIGIO);
  717.   mask |= sigmask(SIGALRM);
  718.   oldmask = sigblock(mask);
  719.   if ((select(0,0,0,0,&tv)) == -1)
  720.   {
  721.     perror("select in wxSleep");
  722.   }
  723.   sigsetmask(oldmask);
  724. #endif
  725. }
  726.