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