ecere/gui/Window: Prevent uninitialized values if base Window methods not overridden...
[sdk] / extras / EnvironmentVariables.ec
1 default:
2
3 #ifdef __WIN32__
4 #define WIN32_LEAN_AND_MEAN
5 #include <windows.h>
6 #include <stdio.h>
7 //#include <tchar.h>
8 //#include <strsafe.h>
9 //#include <tlhelp32.h>
10 #else
11 extern char **environ;
12 #endif
13
14 #if 0
15 #define BUFSIZE 4096
16     TCHAR chNewEnv[BUFSIZE];
17     LPTSTR lpszCurrentVariable;
18     DWORD dwFlags=0;
19     TCHAR szAppName[]=TEXT("ex3.exe");
20     STARTUPINFO si;
21     PROCESS_INFORMATION pi;
22     BOOL fSuccess;
23     // Copy environment strings into an environment block.
24     lpszCurrentVariable = (LPTSTR) chNewEnv;
25     if(FAILED(StringCchCopy(lpszCurrentVariable, BUFSIZE, TEXT("MySetting=A"))))
26     {
27         printf("String copy failed\n");
28         return FALSE;
29     }
30     lpszCurrentVariable += lstrlen(lpszCurrentVariable) + 1;
31     if(FAILED(StringCchCopy(lpszCurrentVariable, BUFSIZE, TEXT("MyVersion=2"))))
32     {
33         printf("String copy failed\n");
34         return FALSE;
35     }
36     // Terminate the block with a NULL byte.
37     lpszCurrentVariable += lstrlen(lpszCurrentVariable) + 1;
38     *lpszCurrentVariable = (TCHAR)0;
39     // Create the child process, specifying a new environment block.
40     SecureZeroMemory(&si, sizeof(STARTUPINFO));
41     si.cb = sizeof(STARTUPINFO);
42 #ifdef UNICODE
43     dwFlags = CREATE_UNICODE_ENVIRONMENT;
44 #endif
45     fSuccess = CreateProcess(szAppName, NULL, NULL, NULL, TRUE, dwFlags,
46         (LPVOID) chNewEnv,   // new environment block
47         NULL, &si, &pi);
48     if(!fSuccess)
49     {
50         printf("CreateProcess failed (%d)\n", GetLastError());
51         return FALSE;
52     }
53     WaitForSingleObject(pi.hProcess, INFINITE);
54     return TRUE;
55 }
56 #endif
57
58 private:
59
60 import "ecere"
61
62 public class SystemEnvironment
63 {
64    property char * { get { return (char *)env; } } // This does not work: property char ** { get { return env; } }
65 private:                                           // unresolved identifier __ecereProp_SystemEnvironment_char__PTR__PTR
66    char ** env;
67    ~SystemEnvironment()
68    {
69 #ifndef __WIN32__
70       char ** p = env;
71       for(; *p; *p++)
72          delete *p;
73 #endif
74       delete env;
75    }
76 }
77
78 void PrintCurrentEnvironment(char * headerLine)
79 {
80    EnvironmentVariables env { };
81    env.AddCurrentEnvVars();
82    if(headerLine)
83       PrintLn(headerLine);
84    env.Print();
85    env.Free();
86    delete env;
87 }
88
89 public class EnvironmentVariables : Map<String, String>
90 {
91    void Print()
92    {
93       if(count)
94       {
95          MapNode<String, String> node;
96          for(node = this.root.minimum; node; node = node.next)
97             PrintLn(node.key, "=", node.value);
98       }
99       else
100          PrintLn("Empty environment!");
101    }
102
103    bool AddCurrentEnvVars()
104    {
105       // TODO: Test char type and unicode correct
106 #ifndef __WIN32__
107       char ** env = environ;
108 #else
109       char * env = GetEnvironmentStrings(); // char * vs LPTCH // TODO: Call GetEnvironmentStringsW function #ifdef UNICODE or something
110 #endif
111       if(env)
112       {
113 #ifndef __WIN32__
114          char * var = *env;
115          for(; var; *env++, var = *env)
116 #else
117          char * var = env; // char * vs LPTSTR
118          for(; *var; var += strlen(var) + 1) // strlen vs lstrlen
119 #endif
120          {
121             char * equal = strstr(var, "=");
122             if(equal && equal != var)
123             {
124                // TODO: check this again, delete varName or not? this[CopyString(varName)] or not?
125                int nameLen = equal-var;
126                char * varName = new char[nameLen+1];
127                char * varVal = equal+1;
128                char * oldVar;
129                strncpy(varName, var, nameLen);
130                varName[nameLen] = '\0';
131                oldVar = this[varName];
132                //*equal = '\0';
133                delete oldVar;
134                this[varName] = CopyString(varVal);
135                //delete varName;
136             }
137          }
138 #ifdef __WIN32__
139          FreeEnvironmentStrings(env);
140 #endif
141       }
142       return (bool)env;
143    }
144
145    void Merge(EnvironmentVariables vars, bool merge)
146    {
147       MapNode<String, String> node;
148       for(node = vars.root.minimum; node; node = node.next)
149       {
150          if(merge)
151             MergeVariableValue(node.key, node.value);
152          else
153             ReplaceVariableValue(node.key, node.value);
154       }
155    }
156
157    void ReplaceVariableValue(char * varName, char * varValue)
158    {
159       char * oldValue = this[varName];
160       delete oldValue;
161       this[varName] = CopyString(varValue);
162    }
163
164    void MergeVariableValue(char * varName, char * varValue)
165    {
166       int dollarStyleRefIdLen, percentStyleRefIdLen;
167       char * dollarStyleRefId, * dollarStyleRef, * percentStyleRefId, * percentStyleRef;
168       char * oldValue = CopyString(this[varName]);
169
170       dollarStyleRefIdLen = strlen(varName)+3;
171       dollarStyleRefId = new char[dollarStyleRefIdLen+1];
172       sprintf(dollarStyleRefId, "$(%s)", varName);
173       dollarStyleRef = strstr(varValue, dollarStyleRefId);
174
175       percentStyleRefIdLen = strlen(varName)+2;
176       percentStyleRefId = new char[percentStyleRefIdLen+1];
177       sprintf(percentStyleRefId, "%%%s%%", varName);
178       percentStyleRef = strstr(varValue, percentStyleRefId);
179
180       // TODO: Make this a loop to replace multiple instances of both dollar and percent style references
181       if(dollarStyleRef)
182       {
183          int beforeLen, oldValLen, afterLen;
184          char * mergedValue;
185          beforeLen = dollarStyleRef - varValue;
186          dollarStyleRef += dollarStyleRefIdLen;
187          afterLen = strlen(dollarStyleRef);
188          oldValLen = oldValue ? strlen(oldValue) : 0;
189          mergedValue = new char[beforeLen + oldValLen + afterLen + 1];
190          strncpy(mergedValue, varValue, beforeLen);
191          mergedValue[beforeLen] = '\0';
192          if(oldValue)
193             strcat(mergedValue, oldValue);
194          strcat(mergedValue, dollarStyleRef);
195          this[varName] = mergedValue;
196       }
197       else if(percentStyleRef)
198       {
199          int beforeLen, oldValLen, afterLen;
200          char * mergedValue;
201          beforeLen = percentStyleRef - varValue;
202          percentStyleRef += percentStyleRefIdLen;
203          afterLen = strlen(percentStyleRef);
204          oldValLen = oldValue ? strlen(oldValue) : 0;
205          mergedValue = new char[beforeLen + oldValLen + afterLen + 1];
206          strncpy(mergedValue, varValue, beforeLen);
207          mergedValue[beforeLen] = '\0';
208          if(oldValue)
209             strcat(mergedValue, oldValue);
210          strcat(mergedValue, percentStyleRef);
211          this[varName] = mergedValue;
212       }
213       else
214          this[varName] = CopyString(varValue);
215
216       delete dollarStyleRefId;
217       delete percentStyleRefId;
218       delete oldValue;
219    }
220
221    void SetAll()
222    {
223       MapNode<String, String> node;
224       for(node = this.root.minimum; node; node = node.next)
225          SetEnvironment(node.key, node.value);
226    }
227
228    SystemEnvironment GetSystemEnvStrings(int * bufferSize)
229    {
230       MapNode<String, String> node;
231       SystemEnvironment output { };
232 #ifndef __WIN32__
233       char ** env = output.env = new char * [this.count+1];
234       for(node = this.root.minimum; node; node = node.next)
235       {
236          *env = new char [strlen(node.key) + strlen(node.value) + 2];
237          sprintf(*env, "%s=%s", node.key, node.value);
238          *env++;
239       }
240       *env = null;
241 #else
242       // TODO: Make sure len vs byte len, unicode and all that is correct
243       int len = 0;
244       char * string;
245       for(node = this.root.minimum; node; node = node.next)
246          len += strlen(node.key) + strlen(node.value) + 2;
247       len++;
248       if(bufferSize)
249          *bufferSize = len;
250       output.env = (char **)new char[len];
251       string = (char *)output.env;
252       for(node = this.root.minimum; node; node = node.next)
253       {
254          sprintf(string, "%s=%s", node.key, node.value);
255          string += strlen(node.key) + strlen(node.value) + 2;
256       }
257       *string = '\0';
258 #endif
259       return output;
260    }
261
262    ~EnvironmentVariables()
263    {
264       for(string : this)
265          delete string;
266    }
267 }