add more spacing
[personal-kdebase.git] / workspace / kcontrol / kfontinst / lib / Misc.cpp
blob141f595cf2be6fcf724894a8a6f06fab0c999542
1 /*
2 * KFontInst - KDE Font Installer
4 * Copyright 2003-2007 Craig Drummond <craig@kde.org>
6 * ----
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; see the file COPYING. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
24 #include "Misc.h"
25 #include <QtCore/QDir>
26 #include <QtCore/QFile>
27 #include <QtCore/QByteArray>
28 #include <QtCore/QTextCodec>
29 #include <QtCore/QTextStream>
30 #include <QtCore/QProcess>
31 #include <QtCore/QTemporaryFile>
32 #include <KDE/KStandardDirs>
33 #include <kde_file.h>
34 #include <unistd.h>
35 #include <ctype.h>
37 namespace KFI
40 namespace Misc
43 QString prettyUrl(const KUrl &url)
45 QString u(url.prettyUrl());
47 u.replace("%20", " ");
48 return u;
51 QString dirSyntax(const QString &d)
53 if(!d.isEmpty())
55 QString ds(d);
57 ds.replace("//", "/");
59 int slashPos(ds.lastIndexOf('/'));
61 if(slashPos!=(((int)ds.length())-1))
62 ds.append('/');
64 return ds;
67 return d;
70 QString fileSyntax(const QString &d)
72 if(!d.isEmpty())
74 QString ds(d);
76 ds.replace("//", "/");
78 int slashPos(ds.lastIndexOf('/'));
80 if(slashPos==(((int)ds.length())-1))
81 ds.remove(slashPos, 1);
82 return ds;
85 return d;
88 QString getDir(const QString &f)
90 QString d(f);
92 int slashPos(d.lastIndexOf('/'));
94 if(slashPos!=-1)
95 d.remove(slashPos+1, d.length());
97 return dirSyntax(d);
100 QString getFile(const QString &f)
102 QString d(f);
104 int slashPos=d.lastIndexOf('/');
106 if(slashPos!=-1)
107 d.remove(0, slashPos+1);
109 return d;
112 bool createDir(const QString &dir)
115 // Clear any umask before dir is created
116 mode_t oldMask(umask(0000));
117 bool status(KStandardDirs::makeDir(dir, DIR_PERMS));
118 // Reset umask
119 ::umask(oldMask);
120 return status;
123 void setFilePerms(const QByteArray &f)
126 // Clear any umask before setting file perms
127 mode_t oldMask(umask(0000));
128 ::chmod(f.constData(), FILE_PERMS);
129 // Reset umask
130 ::umask(oldMask);
133 bool doCmd(const QString &cmd, const QString &p1, const QString &p2, const QString &p3)
135 QStringList args;
137 if(!p1.isEmpty())
138 args << p1;
139 if(!p2.isEmpty())
140 args << p2;
141 if(!p3.isEmpty())
142 args << p3;
144 return 0==QProcess::execute(cmd, args);
147 QString changeExt(const QString &f, const QString &newExt)
149 QString newStr(f);
150 int dotPos(newStr.lastIndexOf('.'));
152 if(-1==dotPos)
153 newStr+=QChar('.')+newExt;
154 else
156 newStr.remove(dotPos+1, newStr.length());
157 newStr+=newExt;
159 return newStr;
163 // Get a list of files associated with a file, e.g.:
165 // File: /home/a/courier.pfa
167 // Associated: /home/a/courier.afm /home/a/courier.pfm
169 void getAssociatedFiles(const QString &path, QStringList &files, bool afmAndPfm)
171 QString ext(path);
172 int dotPos(ext.lastIndexOf('.'));
173 bool check(false);
175 if(-1==dotPos) // Hmm, no extension - check anyway...
176 check=true;
177 else // Cool, got an extension - see if its a Type1 font...
179 ext=ext.mid(dotPos+1);
180 check=0==ext.compare("pfa", Qt::CaseInsensitive) ||
181 0==ext.compare("pfb", Qt::CaseInsensitive);
184 if(check)
186 const char *afm[]={"afm", "AFM", "Afm", NULL},
187 *pfm[]={"pfm", "PFM", "Pfm", NULL};
188 bool gotAfm(false);
189 int e;
191 for(e=0; afm[e]; ++e)
193 QString statFile(changeExt(path, afm[e]));
195 if(fExists(statFile))
197 files.append(statFile);
198 gotAfm=true;
199 break;
203 if(afmAndPfm || !gotAfm)
204 for(e=0; pfm[e]; ++e)
206 QString statFile(changeExt(path, pfm[e]));
208 if(fExists(statFile))
210 files.append(statFile);
211 break;
217 time_t getTimeStamp(const QString &item)
219 KDE_struct_stat info;
221 return !item.isEmpty() && 0==KDE_lstat(QFile::encodeName(item), &info) ? info.st_mtime : 0;
225 bool check(const QString &path, bool file, bool checkW)
227 KDE_struct_stat info;
228 QByteArray pathC(QFile::encodeName(path));
230 return 0==KDE_lstat(pathC, &info) &&
231 (file ? (S_ISREG(info.st_mode) || S_ISLNK(info.st_mode))
232 : S_ISDIR(info.st_mode)) &&
233 (!checkW || 0==::access(pathC, W_OK));
236 QString getFolder(const QString &defaultDir, const QString &root, QStringList &dirs)
238 if(dirs.contains(defaultDir))
239 return defaultDir;
240 else
242 QStringList::const_iterator it,
243 end=dirs.constEnd();
244 bool found=false;
246 for(it=dirs.constBegin(); it!=end && !found; ++it)
247 if(0==(*it).indexOf(root))
248 return *it;
251 return QString();
254 bool checkExt(const QString &fname, const QString &ext)
256 QString extension('.'+ext);
258 return fname.length()>extension.length()
259 ? 0==fname.mid(fname.length()-extension.length()).compare(extension, Qt::CaseInsensitive)
260 : false;
263 bool isMetrics(const QString &str)
265 return checkExt(str, "afm") || checkExt(str, "pfm");
268 int getIntQueryVal(const KUrl &url, const char *key, int defVal)
270 QString item(url.queryItem(key));
271 int val(defVal);
273 if(!item.isNull())
274 val=item.toInt();
276 return val;
279 bool printable(const QString &mime)
281 return "application/x-font-type1"==mime || "application/x-font-ttf"==mime ||
282 "application/x-font-otf"==mime || "application/x-font-type1"==mime;
285 uint qHash(const KFI::Misc::TFont &key)
287 //return qHash(QString(key.family+'%'+QString().setNum(key.styleInfo, 16)));
288 const QChar *p = key.family.unicode();
289 int n = key.family.size();
290 uint h = 0,
293 h = (h << 4) + key.styleInfo;
294 if ((g = (h & 0xf0000000)) != 0)
295 h ^= g >> 23;
296 h &= ~g;
298 while (n--)
300 h = (h << 4) + (*p++).unicode();
301 if ((g = (h & 0xf0000000)) != 0)
302 h ^= g >> 23;
303 h &= ~g;
305 return h;
309 // mkfontscale doesn't ingore hidden files :-(
310 static void removeHiddenEntries(const QString &file)
312 QStringList lines;
313 QFile f(file);
315 if(f.open(QIODevice::ReadOnly))
317 QTextStream stream(&f);
318 QString line;
320 int lineCount=stream.readLine().toInt(); // Ignore line count...
322 while(!stream.atEnd())
324 line=stream.readLine();
325 if(line.length() && '.'!=line[0])
326 lines.append(line);
328 f.close();
330 if(lineCount!=lines.count())
332 QTemporaryFile temp;
334 temp.setAutoRemove(false);
336 if(!temp.open())
337 return;
339 QFile out(temp.fileName());
341 if(out.open(QIODevice::WriteOnly))
343 QTextStream stream(&out);
344 QStringList::ConstIterator it(lines.begin()),
345 end(lines.end());
347 stream << lines.count() << endl;
348 for(; it!=end; ++it)
349 stream << (*it).toLocal8Bit() << endl;
351 out.setPermissions(QFile::ReadOwner|QFile::WriteOwner|
352 QFile::ReadGroup|QFile::ReadOther);
353 out.close();
354 ::rename(QFile::encodeName(out.fileName()), QFile::encodeName(file));
356 else
357 temp.setAutoRemove(true);
362 bool configureForX11(const QString &dir)
365 // On systems without mkfontscale, the following will fail, so cant base
366 // return value upon that - hence only check return value of mkfontdir
367 doCmd("mkfontscale", QFile::encodeName(dir));
368 removeHiddenEntries(dir+"fonts.scale");
369 bool rv=doCmd("mkfontdir", QFile::encodeName(dir));
370 removeHiddenEntries(dir+"fonts.dir");
371 return rv;
374 // Taken from qdom.cpp
375 QString encodeText(const QString &str, QTextStream &s)
377 const QTextCodec *const codec = s.codec();
379 Q_ASSERT(codec);
381 QString retval(str);
382 int len = retval.length(),
383 i = 0;
385 while (i < len)
387 const QChar ati(retval.at(i));
389 if (ati == QLatin1Char('<'))
391 retval.replace(i, 1, QLatin1String("&lt;"));
392 len += 3;
393 i += 4;
395 else if (ati == QLatin1Char('"'))
397 retval.replace(i, 1, QLatin1String("&quot;"));
398 len += 5;
399 i += 6;
401 else if (ati == QLatin1Char('&'))
403 retval.replace(i, 1, QLatin1String("&amp;"));
404 len += 4;
405 i += 5;
407 else if (ati == QLatin1Char('>') && i >= 2 && retval[i - 1] == QLatin1Char(']') && retval[i - 2] == QLatin1Char(']'))
409 retval.replace(i, 1, QLatin1String("&gt;"));
410 len += 3;
411 i += 4;
413 else
415 if(codec->canEncode(ati))
416 ++i;
417 else
419 // We have to use a character reference to get it through.
420 const ushort codepoint(ati.unicode());
421 const QString replacement(QLatin1String("&#x") + QString::number(codepoint, 16) + QLatin1Char(';'));
422 retval.replace(i, 1, replacement);
423 i += replacement.length();
424 len += replacement.length() - 1;
429 return retval;
432 QString contractHome(QString path)
434 if (!path.isEmpty() && '/'==path[0])
436 QString home(QDir::homePath());
438 if(path.startsWith(home))
440 int len = home.length();
442 if(len>1 && (path.length() == len || path[len] == '/'))
443 return path.replace(0, len, QString::fromLatin1("~"));
447 return path;
450 } // Misc::
452 } // KFI::