]> git.lyx.org Git - lyx.git/blob - src/support/os_os2.C
* lyxfunctional.h: delete compare_memfun and helper classes
[lyx.git] / src / support / os_os2.C
1 /**
2  * \file os_os2.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Ruurd A. Reitsma
7  *
8  * Full author contact details are available in file CREDITS.
9  *
10  * Various OS specific functions
11  */
12
13 #include <config.h>
14
15 #include "os.h"
16 #include "support/filetools.h"
17 #define INCL_DOSFILEMGR
18 #define INCL_DOSMODULEMGR
19 #define INCL_DOSPROCESS
20 #define INCL_DOSNLS
21 #define INCL_DOSERRORS
22 #include <os2.h>
23
24 #include <boost/scoped_array.hpp>
25
26 using boost::scoped_array;
27
28 namespace {
29
30 string binpath_;
31 string binname_;
32 string tmpdir_;
33 os::shell_type shell_ = os::UNIX;
34 unsigned long cp_ = 0;
35
36 }
37
38
39 namespace os {
40
41
42 void init(int * argc, char ** argv[])
43 {
44         if (argc != 0 /* This is a hack! */) {
45                 _wildcard(argc, argv);
46                 PTIB ptib = new TIB[1];
47                 PPIB ppib = new PIB[1];
48                 APIRET rc = DosGetInfoBlocks(&ptib, &ppib);
49                 if (rc != NO_ERROR)
50                         exit(rc);
51                 scoped_array<char> tmp(new char[256]);
52                 // This is the only reliable way to retrieve the executable name.
53                 rc = DosQueryModuleName(ppib->pib_hmte, 256L, tmp);
54                 if (rc != NO_ERROR)
55                         exit(rc);
56                 string p = tmp.get();
57                 p = slashify_path(p);
58                 binname_ = OnlyFilename(p);
59                 binname_.erase(binname_.length()-4, string::npos);
60                 binpath_ = OnlyPath(p);
61
62                 // OS/2 cmd.exe has another use for '&'
63                 string sh = OnlyFilename(GetEnvPath("EMXSHELL"));
64                 if (sh.empty()) {
65                         // COMSPEC is set, unless user unsets
66                         sh = OnlyFilename(GetEnvPath("COMSPEC"));
67                         if (sh.empty())
68                                 sh = "cmd.exe";
69                 }
70                 sh = lowercase(sh);     // DosMapCase() is an overkill here
71                 if (contains(sh, "cmd.exe") || contains(sh, "4os2.exe"))
72                         shell_ = os::CMD_EXE;
73                 else
74                         shell_ = os::UNIX;
75         }
76
77         static bool initialized = false;
78         if (initialized)
79                 return;
80         initialized = true;
81
82         ULONG CPList[3] = {0};
83         ULONG CPList_size;
84         APIRET rc = DosQueryCp(3 * sizeof(ULONG), CPList, &CPList_size);
85         if (rc != NO_ERROR)
86                 exit(rc);
87         // CPList[0] == process current codepage,
88         // CPList[1] == system default codepage, the rest are auxilary.
89         // Once cp_ is correctly set, you can call other routines.
90         cp_ = CPList[1];
91 }
92
93
94 void warn(string const & /*mesg*/)
95 {
96         return;
97 }
98
99
100 string current_root()
101 {
102         APIRET rc;
103         ULONG drv_num;
104         ULONG drv_map;
105         rc = DosQueryCurrentDisk(&drv_num, &drv_map);
106         if (rc != NO_ERROR)
107                 exit(rc);
108         char drive = 'A' + drv_num -1;
109         string tmp(1, drive);
110         tmp  += ":/";
111         return tmp;
112 }
113
114
115 string::size_type common_path(string const & p1, string const & p2)
116 {
117         static bool initialized = false;
118         if (!initialized) {
119                 init(0, 0);
120                 initialized = true;
121         }
122
123         COUNTRYCODE cntry;
124         cntry.country = 0;
125         cntry.codepage = cp_;
126         string temp1 = slashify_path(p1);
127         string temp2 = slashify_path(p2);
128         char * tmp1 = const_cast<char *> (temp1.c_str());
129         char * tmp2 = const_cast<char *> (temp2.c_str());
130         /* rc = */ DosMapCase(p1.length(), &cntry, tmp1);
131         // if (rc != NO_ERROR)
132         //      exit(rc);
133         /* rc = */ DosMapCase(p2.length(), &cntry, tmp2);
134         // if (rc != NO_ERROR)
135         //      exit(rc);
136         // This algorithm works only if paths are slashified on DBCS systems.
137         string::size_type i = 0;
138         string::size_type p1_len = p1.length();
139         string::size_type p2_len = p2.length();
140         while (i < p1_len && i < p2_len && tmp1[i] == tmp2[i])
141                 ++i;
142         if ((i < p1_len && i < p2_len)
143             || (i < p1_len && tmp1[i] != '/' && i == p2_len)
144             || (i < p2_len && tmp2[i] != '/' && i == p1_len))
145         {
146                 if (i)
147                         --i;     // here was the last match
148                 while (i && tmp1[i] != '/')
149                         --i;
150         }
151         return i;
152 }
153
154
155 string slashify_path(string const & p)
156 {
157         static bool initialized = false;
158         static bool leadbyte[256] = {false};
159         if (!initialized) {
160                 init(0, 0);
161                 COUNTRYCODE cntry;
162                 cntry.country = 0;
163                 cntry.codepage = cp_;
164                 unsigned char *DBCSinfo = new unsigned char[12];
165                 /* rc = */ DosQueryDBCSEnv(12, &cntry, (char*) DBCSinfo);
166                 // if (rc != NO_ERROR)
167                 //      exit(rc);
168                 for (int j = 1; j < 12; j += 2)
169                         DBCSinfo[j]++;
170                 unsigned char i = 0;
171                 bool isLeadByte = false;
172                 while (*DBCSinfo != 0) {
173                         if (i == *DBCSinfo) {
174                                 isLeadByte = !isLeadByte;
175                                 DBCSinfo++;
176                         }
177                         leadbyte[i++] = isLeadByte;
178                 }
179                 initialized = true;
180         }
181         string::iterator lit = p.begin();
182         string::iterator end = p.end();
183         for (; lit < end; ++lit) {
184                 if (leadbyte[(*lit)])
185                         lit += 2;
186                 if ((*lit) == '\\')
187                         (*lit) = '/';
188         }
189         p = subst(p, "//", "/");
190         return p;
191 }
192
193
194 string external_path(string const & p)
195 {
196         return p;
197 }
198
199
200 string internal_path(string const & p)
201 {
202         return p;
203 }
204
205
206 bool is_absolute_path(string const & p)
207 {
208         return (p.length() > 1
209                 && isalpha(static_cast<unsigned char>(p[0]))
210                 && p[1] == ':');
211 }
212
213
214 // returns a string suitable to be passed to popen when
215 // reading a pipe
216 char const * popen_read_mode()
217 {
218         return "r";
219 }
220
221
222 string binpath()
223 {
224         return binpath_;
225 }
226
227
228 string binname()
229 {
230         return binname_;
231 }
232
233
234 void setTmpDir(string const & p)
235 {
236         tmpdir_ = p;
237 }
238
239
240 string getTmpDir()
241 {
242         return tmpdir_;
243 }
244
245
246 shell_type shell()
247 {
248         return shell_;
249 }
250
251 } // end namespace os