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