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