1 /*
2 miscutil.cpp : This file is part of pstoedit
3 misc utility functions
4
5 Copyright (C) 1998 Wolfgang Glunz, wglunz@geocities.com
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 */
22 #include "miscutil.h"
23
24 #include I_stdio
25
26 // #ifdef _MSC_VER
27 // for getcwd ( at least for Visual C++)
28
29 #if defined(unix) || defined(__unix__) || defined(_unix) || defined(__unix) || defined(__EMX__)
30 #include <unistd.h>
31 #else
32 #include <direct.h>
33 #endif
34
35 #include I_stdlib
36
37 #include I_string_h
38
39
40 #if defined(_WIN32)
41 #include <windows.h>
42 #elif defined (__OS2__)
43 #define INCL_DOS
44 #define INCL_WINWINDOWMGR
45 #define INCL_WINSHELLDATA /* Window Shell functions */
46 #define INCL_WINERRORS
47 #include <os2.h>
48 #endif
49
50
51 #if defined(unix) || defined(__unix__) || defined(_unix) || defined(__unix)
52 //take this out (we may have backslashes w/ EMX(OS/2)): || defined(__EMX__)
convertBackSlashes(char * string)53 void convertBackSlashes(char* string) { unused(string); }
54 // nothing to do on systems with unix style file names ( / for directories)
55 #else
convertBackSlashes(char * string)56 void convertBackSlashes(char* string) {
57
58 char* c;
59
60 while ((c = strchr(string,'\\')) != NULL)
61 *c = '/';
62 }
63 #endif
64
65 #if defined(__STRICT_ANSI__)
66 // normally this is in stdio.h except if __STRICT_ANSI__ is defined (GNU specific)
67 extern "C" char *tempnam(const char *, const char *pfx);
68 #endif
69
70 #if defined(riscos)
71 // rcw2: tempnam doesn't seem to be defined in UnixLib 3.7b for RiscOS
tempnam(const char *,const char * pfx)72 char *tempnam(const char *, const char *pfx)
73 {
74 char tmp[1024];
75
76 strcpy(tmp,"<Wimp$ScrapDir>.");
77 strcat(tmp,pfx);
78 return strdup(tmp);
79 }
80 #endif
81
82 #ifdef __WATCOMC__
83 // tempnam doesn't seem to be defined in Watcoms clibs
tempnam(const char *,const char * pfx)84 char *tempnam(const char *, const char *pfx)
85 {
86 const char* path;
87 char tmp[1024];
88
89 // simply take c: as temp dir, if environment not defined
90 if( (path=getenv("TEMP")) == 0L &&
91 (path=getenv("TMP")) == 0L )
92 {
93 strcpy(tmp,"C:\\");
94 }
95 else
96 {
97 // take temp dir from environment
98 strcpy(tmp,path);
99 strcat(tmp,"\\");
100 }
101
102 strcat(tmp,pfx);
103
104 // remove all backslashes
105 convertBackSlashes(tmp);
106
107 return strdup(tmp);
108 }
109 #endif
110
111 // #define BUGGYTEMPNAM
112
113 #if defined(DJGPP) && defined(BUGGYTEMPNAM)
114 // tempnam under DJGPP behaves different than on all other systems
tempnam(const char *,const char * pfx)115 char *tempnam(const char *, const char *pfx)
116 {
117 return strdup(tmpnam(0));
118 }
119 #endif
120
full_qualified_tempnam(const char * pref)121 char * full_qualified_tempnam(const char * pref)
122 {
123 #if defined (__BCPLUSPLUS__) || defined (__TCPLUSPLUS__)
124 /* borland has a prototype that expects a char * as second arg */
125 char * filename = tempnam(0,(char *) pref);
126 #else
127 char * filename = tempnam(0,pref);
128 #endif
129 // W95: Fkt. tempnam() erzeugt Filename+Pfad
130 // W3.1: es wird nur der Name zurueckgegeben
131
132 // rcw2: work round weird RiscOS naming conventions
133 #ifdef riscos
134 return filename;
135 #else
136 convertBackSlashes(filename);
137 if ( (strchr(filename,'\\')==0) &&
138 (strchr(filename,'/') ==0) ) { // keine Pfadangaben..
139 char cwd[400];
140 getcwd(cwd,400);
141 char * result = new char [strlen(filename) + strlen(cwd) + 2];
142 strcpy(result,cwd);
143 strcat(result,"/");
144 strcat(result,filename);
145 free(filename);
146 return result;
147 } else {
148 return filename;
149 }
150 #endif
151 }
152
153 // a strdup which uses new instead of malloc
cppstrdup(const char * src)154 char * cppstrdup(const char * src)
155 {
156 char * ret = new char [strlen(src) + 1];
157 strcpy(ret,src);
158 return ret;
159 }
160
161 #if defined(_WIN32)
tryregistry(HKEY hKey,LPCSTR subkeyn,LPCSTR key)162 char * tryregistry(HKEY hKey,LPCSTR subkeyn, LPCSTR key)
163 {
164 HKEY subkey;
165 const long ret = RegOpenKeyEx (
166 hKey, // HKEY_LOCAL_MACHINE, //HKEY hKey,
167 subkeyn, // LPCSTR lpSubKey,
168 0L , // DWORD ulOptions,
169 KEY_READ , // REGSAM samDesired,
170 &subkey //PHKEY phkResult
171 );
172 if ( ret != ERROR_SUCCESS) {
173 // errstream << "RegOpenKeyEx failed with error code " << ret << endl;
174 return 0;
175 } else {
176 const int maxvaluelength = 1000;
177 BYTE value[maxvaluelength];
178 DWORD bufsize = maxvaluelength;
179 DWORD valuetype ;
180 const long retv = RegQueryValueEx (
181 subkey, // HKEY_LOCAL_MACHINE, //HKEY hKey,
182 key, // "SOFTWARE\\wglunz\\pstoedit\\plugindir", //LPCSTR lpValueName,
183 NULL, // LPDWORD lpReserved,
184 &valuetype, // LPDWORD lpType,
185 value, // LPBYTE lpData,
186 &bufsize // LPDWORD lpcbData
187 );
188 RegCloseKey(subkey);
189 if ( retv != ERROR_SUCCESS) {
190 // errstream << "RegQueryValueEx failed with error code " << retv << endl;
191 return 0;
192 } else {
193 // errstream << "result is " << dirname << endl;
194 return cppstrdup( (const char *) value);
195 }
196 }
197 }
198
199 #endif
200
201 #ifdef __OS2__
202 #include "getini.c"
203 #endif
204
getRegistryValue(ostream & errstream,const char * typekey,const char * key)205 char * getRegistryValue(ostream& errstream, const char * typekey, const char * key) {
206 #if defined(_WIN32)
207
208 // CString subkey = CString("SOFTWARE\\wglunz\\") + CString(product);
209 char subkeyn[1000];
210 subkeyn[0] = '\0';
211 strcat(subkeyn,"SOFTWARE\\wglunz\\");
212 strcat(subkeyn,typekey);
213 char * result = tryregistry(HKEY_CURRENT_USER,subkeyn,key);
214 if (!result) result = tryregistry(HKEY_LOCAL_MACHINE ,subkeyn,key);
215 return result;
216 #elif defined (__OS2__)
217 //query a "real" OS/2 profile pstoedit.ini
218 HINI hini;
219 HAB hab;
220 char pszFileName [1000];
221 const char inifilename[] = "pstoedit.ini";
222 APIRET rc;
223 char buffer[1000];
224
225 hab = WinInitialize( 0 );
226
227 getini(0,errstream,pszFileName,inifilename,
228 (int)sizeof(pszFileName));
229 hini = PrfOpenProfile( hab, pszFileName);
230 rc=PrfQueryProfileString( hini, typekey, key,
231 NULL, (PVOID)buffer, (LONG)sizeof(buffer));
232 PrfCloseProfile(hini);
233 WinTerminate(hab);
234
235 if (rc)
236 {
237 char * r = cppstrdup(buffer);
238 return r;
239 }
240 else return 0;
241 #else
242 //
243 // UNIX version
244 // Just ask the environment
245 //
246 #if 0
247 //getenv version
248 char envname[1000];
249 envname[0] = '\0';
250 strcat(envname,typekey);
251 strcat(envname,"_");
252 strcat(envname,key);
253 // cout << "checking " << envname << endl;
254 char * envvalue = getenv(envname);
255 if (envvalue != 0) {
256 char * r = cppstrdup(envvalue);
257 // cout << "found " << r << endl;
258 return r;
259 } else return 0;
260 #else
261 char envname[1000];
262 envname[0] = '\0';
263 strcat(envname,typekey);
264 strcat(envname,"/");
265 strcat(envname,key);
266 // cout << "checking " << envname << endl;
267 const char * homedir = getenv("HOME");
268 if (!homedir) return 0;
269 const int len = strlen(homedir) + 20;
270 char * obuf = new char[len ];
271 strcpy(obuf,homedir);
272 strcat(obuf,"/.pstoedit.reg");
273 ifstream regfile(obuf);
274 // cout << "opened " << obuf << endl;
275 delete []obuf;
276 if (!regfile) return 0;
277 char line [1000];
278 while (!regfile.eof()) {
279 regfile.getline(line,1000);
280 // cout << line << endl;
281 if (strstr(line,envname)) {
282 char * r = cppstrdup(line+strlen(envname)+1);
283 char * cr = strrchr(r,'\r');
284 if (cr) *cr = 0;
285 // cout << "found " << r << endl;
286 return r;
287 }
288 }
289 return 0;
290 #endif
291 #endif
292 }
293
copy_file(istream & infile,ostream & outfile)294 void copy_file(istream& infile,ostream& outfile)
295 {
296 #if 1
297 outfile << infile.rdbuf();
298 #else
299 // long version. should do the same as above
300 unsigned char c;
301 while (infile.get(c)) {
302 outfile.put(c);
303 }
304 #endif
305 }
306
operator <<(ostream & out,const Argv & a)307 ostream & operator <<(ostream & out, const Argv & a)
308 {
309 for (unsigned int i = 0; i < (unsigned) a.argc; i++) {
310 out << a.argv[i]; out << endl;
311 }
312 return out;
313 }
314
315
TempFile()316 TempFile::TempFile()
317 {
318 tempFileName = tempnam(0,"pstmp");
319 // cout << "constructed " << tempFileName << endl;
320 }
321
~TempFile()322 TempFile::~TempFile()
323 {
324 // cout << "detructed " << tempFileName << endl;
325 close();
326 remove(tempFileName);
327 free(tempFileName);
328 }
329
asOutput()330 ofstream & TempFile::asOutput()
331 {
332 close();
333 outFileStream.open(tempFileName);
334 if (outFileStream.fail()) cerr << "openening " << tempFileName << "failed " << endl;
335 return outFileStream;
336 }
337
asInput()338 ifstream & TempFile::asInput()
339 {
340 close();
341 inFileStream.open(tempFileName);
342 if (outFileStream.fail()) cerr << "openening " << tempFileName << "failed " << endl;
343 return inFileStream;
344 }
345
close()346 void TempFile::close()
347 {
348 //#ifdef HAVE_IS_OPEN
349 //#define IS_OPEN(file) file.is_open()
350 //#else
351 //#define IS_OPEN(file) file
352 //#endif
353 // commented, since it also works portably if we call clear()
354
355 // if (IS_OPEN(inFileStream)) {
356 inFileStream.close();
357 // if (inFileStream.fail()) cerr << "closing inFileStream failed " << endl;
358 // }
359 inFileStream.clear();
360 // if (IS_OPEN(outFileStream)) {
361 outFileStream.close();
362 // if (outFileStream.fail()) cerr << "closing outFileStream failed " << endl;
363 // }
364 outFileStream.clear();
365 }
366
367
368 #if 0
369 void freeconst(const void *ptr)
370 {
371 free((char *)ptr); // just to have the warning about casting away constness
372 // once (here)
373 }
374 #endif
375
P_GetPathToMyself(const char * name,char * returnbuffer,unsigned long buflen)376 unsigned long P_GetPathToMyself(const char *name,char * returnbuffer, unsigned long buflen)
377 {
378 #if defined(_WIN32)
379 return GetModuleFileName(GetModuleHandle(name),returnbuffer,buflen);
380 #elif defined (__OS2__)
381 PTIB pptib;
382 PPIB pppib;
383 APIRET rc;
384 if ( (rc=DosGetInfoBlocks(&pptib, &pppib)) == 0 )
385 if ( (rc=DosQueryModuleName(pppib->pib_hmte, buflen,
386 returnbuffer)) == 0 )
387 return strlen(returnbuffer);
388 else
389 return 0;
390 else
391 return 0;
392 #else
393 if (*name == '/' ) { // starts with /
394 strcpy(returnbuffer,name);
395 return strlen(returnbuffer);
396 } else {
397 const char * EnvPath = getenv("PATH");
398 if (!EnvPath) return 0;
399 char * path = cppstrdup(EnvPath);
400 char * colon = path;
401 char * lastbegin = path;
402 while (*colon) {
403 while (*colon && (*colon !=':')) colon++;
404 if (*colon) {
405 *colon='\0';
406 RSString test(lastbegin);
407 test+="/";
408 test+=name;
409 if (fileExists(test.value())) {
410 strcpy(returnbuffer,test.value());
411 delete [] path;
412 return strlen(returnbuffer);
413 }
414 }
415 colon++;
416 lastbegin=colon;
417 }
418 delete [] path;
419 }
420 return 0; // not found
421 #endif
422 }
423
errorMessage(const char * text)424 void errorMessage(const char * text)
425 {
426 #if defined(_WIN32)
427 MessageBox(NULL, text, "pstoedit", MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
428 #else
429 cerr << text << endl;
430 #endif
431 }
432
433 // a very very simple resizing string
RSString(const char * arg)434 RSString::RSString(const char * arg) :
435 content(0),
436 allocatedLength(0) {
437 if (arg) this->copy(arg);
438 // cerr << "{ constructed" << (void*) this << endl;
439 }
RSString(const RSString & s)440 RSString::RSString(const RSString & s) : content(0),allocatedLength(0) {
441 assert(this != &s);
442 this->copy(s.value());
443 }
444
newContent(unsigned int size)445 char * RSString::newContent(unsigned int size) {
446 return new char[size];
447 }
448
clearContent()449 void RSString::clearContent() {
450 delete [] content;
451 content = 0;
452 }
453
~RSString()454 RSString::~RSString() {
455 // cerr << (void*) this << "deleted }" << endl;
456 clearContent();
457 allocatedLength = 0;
458 }
459
operator +=(const RSString & rs)460 const RSString& RSString::operator+= (const RSString &rs) {
461 unsigned int newlen = strlen(content)+ strlen(rs.content) + 1;
462 char * newstring = newContent(newlen);
463 strcpy(newstring,content);
464 strcat(newstring,rs.content);
465 clearContent();;
466 content = newstring;
467 allocatedLength = newlen;
468 return *this;
469 }
470 // const char * value() const { return content; }
copy(const char * src)471 void RSString::copy(const char *src) {
472 // cerr << "copy " << src << " to " << (void *) this << endl;
473 if ( content && ((strlen(src)+1) <= allocatedLength)) {
474 // we have enough space
475 ::strcpy(content,src);
476 } else {
477 // resize
478 // cerr << "content before delete is " << (void *) content << endl;
479 clearContent();
480 allocatedLength = strlen(src) + 1;
481 content = newContent(allocatedLength);
482 // cerr << "content after new is " << (void *) content << endl;
483 ::strcpy(content,src);
484 }
485 }
486
fileExists(const char * filename)487 bool fileExists (const char * filename)
488 {
489 #ifdef HAVESTL
490 std::ifstream test(filename);
491 return test.is_open();
492 #else
493 ifstream test(filename, ios::in | ios::nocreate);
494 // MSVC neede ios::nocreate if used for testing whether file exists
495 return test ? true : false;
496 #endif
497 }
498
499
500 //FontMapper::~FontMapper() {
501 // cerr << "destroying FontMapper" << endl;
502
503 //}
504
skipws(char * & lineptr)505 static void skipws(char * & lineptr) {
506 while ((*lineptr != '\0') && (*lineptr == ' ') || (*lineptr == '\t')) lineptr++;
507 return ;
508 }
509
readword(char * & lineptr)510 static char * readword( char * & lineptr) {
511 char * result = 0;
512 if (*lineptr == '"') {
513 result = strtok(lineptr,"\"");
514 } else {
515 result = strtok(lineptr,"\t ");
516 }
517 if (result) {
518 lineptr = result + strlen(result) + 1;
519 }
520 return result;
521 }
522
readMappingTable(ostream & errstream,const char * filename)523 void FontMapper::readMappingTable(ostream & errstream, const char * filename)
524 {
525 if (!fileExists(filename)) {
526 errstream << "Could not open font map file " << filename << endl;
527 return;
528 }
529 ifstream inFile(filename);
530 const int linesize = 255;
531 char line[linesize];
532 char save[linesize];
533 unsigned int linenr = 0;
534 while (!inFile.getline(line,linesize).eof()) {
535 linenr++;
536 strcpy(save,line);
537 #ifdef HAVESTL
538 // Notes regarding ANSI C++ version (from KB)
539 // istream::get( char* pch, int nCount, char delim ) is different in three ways:
540 // When nothing is read, failbit is set.
541 // An eos is always stored after characters extracted (this happens regardless of the outcome).
542 // A value of -1 for nCount is an error.
543
544 // If the line contains just a \n then the failbit
545 // is set in the ANSI version
546 if (inFile.gcount() == 0) { inFile.clear(); continue; }
547 #endif
548 if (line[0] == '%') continue;
549 char * lineptr = line;
550 //skip initial spaces
551 skipws(lineptr);
552 char * original = readword(lineptr);
553 skipws(lineptr);
554 char * replacement = readword(lineptr);
555 if (original && replacement) {
556 // errstream << "\"" << original << "\" \"" << replacement <<"\""<< endl;
557 insert(original, replacement);
558 } else {
559 errstream << "wrongly formatted line(" << linenr << ") found in fontmap: " << save << endl;
560 }
561 }
562 }
563
mapFont(const RSString & fontname)564 const char * FontMapper::mapFont(const RSString & fontname)
565 {
566 #if 0
567 FontMapping * curEntry = firstEntry;
568 // cerr << "Trying to remap font" << fontname << endl;
569 while (curEntry != 0) {
570 // cerr << "comparing with" << curEntry->original << endl;
571 if (curEntry->original == RSString(fontname) ) {
572 // cerr << "mapped to " << curEntry->replacement.value() << endl;
573 return curEntry->replacement.value();
574 }
575 curEntry=curEntry->nextEntry;
576 }
577 return 0;
578 #endif
579 const RSString * r = getValue(fontname);
580 if (r) return r->value(); else return 0;
581 }
582
583
584