00001
00002
00003
00004
00005
00006 extern "C" {
00007 #include <unistd.h>
00008 #include <X11/Xlib.h>
00009 }
00010
00011 #include <sstream>
00012 #include <iostream>
00013
00014 #include "util.h"
00015
00016 #include "action.h"
00017
00018 #include "rectangle.h"
00019
00020 Util::Util() {
00021 }
00022
00023 Util::~Util() {
00024 }
00025
00026 string Util::lowerCase(string str) {
00027 string input = str;
00028
00029 for (string::iterator it = input.begin(); it != input.end(); it++) {
00030 *it = tolower(*it);
00031 }
00032
00033 return input;
00034 }
00035
00036 bool Util::containsWhitespaces(string str) {
00037
00038 for (string::iterator it = str.begin(); it != str.end(); it++) {
00039 if (*it == ' ' || *it == '\t') {
00040 return true;
00041 }
00042 }
00043
00044 return false;
00045 }
00046
00047 string Util::truncate(string str, char c) {
00048
00049 string result = "";
00050
00051 for (string::iterator it = str.begin(); it != str.end(); it++) {
00052 if ((*it != c) && (*it != '\t')) {
00053 result += *it;
00054 }
00055 }
00056
00057 return result;
00058 }
00059
00060 string Util::canonicalDir(string path) {
00061 string dir = canonicalPath(path);
00062 unsigned int pos = 0;
00063
00064 pos = dir.find_last_of('/');
00065 if (pos != string::npos) {
00066 dir = dir.substr(0, pos);
00067 }
00068
00069 return dir;
00070 }
00071
00072 string Util::canonicalPath(string file) {
00073
00074 string result = "";
00075 for (string::iterator it = file.begin(); it != file.end(); it++) {
00076
00077 if (*it == '~') {
00078 char *home = getenv("HOME");
00079
00080
00081 if (home == 0) {
00082 cerr << "ncwm[E " << timestamp() << "]: "
00083 << "Util::canonicalPath() cannot determine your "
00084 << "$HOME directory, giving up";
00085 exit(1);
00086 }
00087
00088 result += home;
00089 }
00090 else {
00091 result += *it;
00092 }
00093 }
00094 return result;
00095 }
00096
00097 string Util::encodeEscapes(string str) {
00098 string encoded = "";
00099
00100 for (string::iterator it = str.begin(); it != str.end(); it++) {
00101 switch (*it) {
00102 case '\\':
00103 encoded += "\\\\";
00104 break;
00105 case '#':
00106 encoded += "\\#";
00107 break;
00108 case '"':
00109 encoded += "\\\"";
00110 break;
00111 case '=':
00112 encoded += "\\=";
00113 break;
00114 default:
00115 encoded += *it;
00116 break;
00117 }
00118 }
00119
00120 return encoded;
00121 }
00122
00123 string Util::lastToken(string str, char delim) {
00124
00125 string result = "";
00126 unsigned int pos = str.find_last_of(delim);
00127
00128 if (pos != string::npos) {
00129 result = str.substr(pos + 1, str.length() - pos);
00130 }
00131
00132 return result;
00133 }
00134
00135 string Util::nthToken(string str, char delim, unsigned int n) {
00136
00137 unsigned int delimCounter = 1;
00138 string token = "";
00139
00140 for (string::iterator it = str.begin(); it != str.end(); it++) {
00141
00142 if (*it == delim) {
00143 delimCounter++;
00144 continue;
00145 }
00146
00147
00148 if (delimCounter == n) {
00149 token += *it;
00150 }
00151 else if (delimCounter > n) {
00152 return token;
00153 }
00154 }
00155
00156 return token;
00157 }
00158
00159 char **Util::arguments(string command) {
00160
00161 string arg = "";
00162 list<const char *> args;
00163
00164 bool proceed = true;
00165 for (string::iterator it = command.begin(); proceed; it++) {
00166
00167 proceed = it != command.end();
00168 if (!proceed || (*it == ' ') || (*it == '\t'))
00169 {
00170 if (arg.length() > 0) {
00171 args.push_back((new string(arg))->c_str());
00172 }
00173 arg = "";
00174 }
00175 else {
00176 arg += *it;
00177 }
00178 }
00179
00180 const char **result = new const char *[args.size() + 1];
00181 unsigned int i = 0;
00182 for (list<const char *>::iterator it = args.begin();
00183 it != args.end(); it++, i++)
00184 {
00185 result[i] = *it;
00186 }
00187 result[i] = 0;
00188
00189 return (char **)result;
00190 }
00191
00192 unsigned int Util::numDigits(unsigned int number)
00193 {
00194 unsigned int n = 0;
00195 do {
00196 ++n; number /= 10;
00197 } while (number);
00198
00199 return n;
00200 }
00201
00202 string Util::timestamp() {
00203 static time_t utctime;
00204 static struct tm *todaylocal;
00205 static char timestamp[16];
00206 time(&utctime);
00207 todaylocal = localtime(&utctime);
00208 strftime(timestamp, 16,"%Y%m%d%H%M%S", todaylocal);
00209
00210 return (string)timestamp;
00211 }
00212
00213 string Util::stringForButton(unsigned int button) {
00214 ostringstream oss;
00215
00216 oss << "Button" << button;
00217 return oss.str();
00218 }
00219
00220 unsigned int Util::buttonForString(string button) {
00221
00222 if (button.find("Button1") != string::npos) {
00223 return Button1;
00224 }
00225 else if (button.find("Button2") != string::npos) {
00226 return Button2;
00227 }
00228 else if (button.find("Button3") != string::npos) {
00229 return Button3;
00230 }
00231 else if (button.find("Button4") != string::npos) {
00232 return Button4;
00233 }
00234 else if (button.find("Button5") != string::npos) {
00235 return Button5;
00236 }
00237
00238 return 0;
00239 }
00240
00241 string Util::stringForModMask(unsigned long modMask) {
00242
00243 string result = "";
00244 if (modMask & ShiftMask) {
00245 result += "shift + ";
00246 }
00247 if (modMask & LockMask) {
00248 result += "lock + ";
00249 }
00250 if (modMask & ControlMask) {
00251 result += "ctrl + ";
00252 }
00253 if (modMask & Mod1Mask) {
00254 result += "mod1 + ";
00255 }
00256 if (modMask & Mod2Mask) {
00257 result += "mod2 + ";
00258 }
00259 if (modMask & Mod3Mask) {
00260 result += "mod3 + ";
00261 }
00262 if (modMask & Mod4Mask) {
00263 result += "mod4 + ";
00264 }
00265 if (modMask & Mod5Mask) {
00266 result += "mod5 + ";
00267 }
00268 if (!modMask) {
00269 result += "none + ";
00270 }
00271 return result;
00272 }
00273
00274 unsigned long Util::modMaskForString(string modKeys)
00275 {
00276 unsigned long modMask = 0;
00277 if (modKeys.find("shift") != string::npos) {
00278 modMask |= ShiftMask;
00279 }
00280 if (modKeys.find("lock") != string::npos) {
00281 modMask |= LockMask;
00282 }
00283 if ((modKeys.find("control") != string::npos) ||
00284 (modKeys.find("ctrl") != string::npos)) {
00285 modMask |= ControlMask;
00286 }
00287 if ((modKeys.find("alt") != string::npos) ||
00288 (modKeys.find("mod1") != string::npos)) {
00289 modMask |= Mod1Mask;
00290 }
00291 if (modKeys.find("mod2") != string::npos) {
00292 modMask |= Mod2Mask;
00293 }
00294 if (modKeys.find("mod3") != string::npos) {
00295 modMask |= Mod3Mask;
00296 }
00297 if (modKeys.find("mod4") != string::npos) {
00298 modMask |= Mod4Mask;
00299 }
00300 if (modKeys.find("mod5") != string::npos) {
00301 modMask |= Mod5Mask;
00302 }
00303 return modMask;
00304 }
00305
00306 unsigned int Util::strToUInt(string str) {
00307
00308 return atoi(str.c_str());
00309 }
00310
00311 void Util::fitIntoDirection(int horigin, int hw, int *corigin, int *cw)
00312 {
00313 int horigin1 = horigin;
00314 int horigin2 = horigin + hw;
00315 int corigin1 = *corigin;
00316 int corigin2 = *corigin + *cw;
00317
00318 if ((corigin1 < horigin1) && (corigin2 <= horigin2)) {
00319 *corigin = horigin;
00320 if (*corigin + *cw > horigin2) {
00321 *cw = hw;
00322 }
00323 }
00324 else if ((corigin1 < horigin1) && (corigin2 > horigin2)) {
00325 *corigin = horigin;
00326 *cw = hw;
00327 }
00328 else if ((corigin1 >= horigin1) && (corigin2 > horigin2)) {
00329 *cw = horigin2 - *corigin;
00330 }
00331 }
00332
00333
00334 void Util::fitInto(Rectangle *client, Rectangle *host) {
00335
00336 int cx = client->x();
00337 int cw = client->width();
00338
00339 fitIntoDirection(host->x(), host->width(), &cx, &cw);
00340 client->setX(cx);
00341 client->setWidth(cw);
00342
00343 int cy = client->y();
00344 int ch = client->height();
00345
00346 fitIntoDirection(host->y(), host->height(), &cy, &ch);
00347 client->setY(cy);
00348 client->setHeight(ch);
00349 }
00350
00351 Direction Util::dirForString(string str) {
00352
00353 string dirStr;
00354
00355 dirStr = lowerCase(str);
00356
00357 if (dirStr == "left") {
00358 return LEFT;
00359 }
00360 else if (dirStr == "right") {
00361 return RIGHT;
00362 }
00363 else if (dirStr == "up") {
00364 return UP;
00365 }
00366 else {
00367 return DOWN;
00368 }
00369 }
00370
00371 bool Util::exists(const char *path) {
00372
00373 return access(path, F_OK) == 0;
00374 }
00375
00376 string Util::shortenString(string str, unsigned int n) {
00377
00378 return str.substr(0, n) + "...";
00379 }
00380
00381
00382 set<string> Util::stringSplit(string s, string delimiter){
00383 set<string> res;
00384 unsigned int pos = 0;
00385 while (pos != string::npos){
00386 pos = s.find_first_of(delimiter);
00387 res.insert(s.substr(0, pos));
00388 s.erase(0, pos + 1);
00389 }
00390 return(res);
00391 }
00392
00393 string Util::trimL(string s){
00394 return s.substr(s.find_first_not_of(' '));
00395 }
00396
00397
00398 bool Util::isPointWithinRect(unsigned int x, unsigned int y, Rectangle *rect,
00399 Rectangle *offset)
00400 {
00401 unsigned int offsetX = rect->x();
00402 unsigned int offsetY = rect->y();
00403 if (offset) {
00404 offsetX += offset->x();
00405 offsetY += offset->y();
00406 }
00407
00408 return ((offsetX <= x) && (offsetY <= y) &&
00409 (offsetX + rect->width() >= x) &&
00410 (offsetY + rect->height() >= y));
00411 }
00412
00413
00414 void Util::swapChars(string *str, char from, char to,
00415 unsigned int *swapCount)
00416 {
00417 for (string::iterator it = str->begin(); it != str->end(); it++) {
00418 if (*it == from) {
00419 *it = to;
00420 if (swapCount) {
00421 (*swapCount)++;
00422 }
00423 }
00424 }
00425 }
00426
00427 Direction Util::reverseDir(Direction dir) {
00428 switch (dir) {
00429 case LEFT:
00430 return RIGHT;
00431 break;
00432 case RIGHT:
00433 return LEFT;
00434 break;
00435 case UP:
00436 return DOWN;
00437 break;
00438 case DOWN:
00439 return UP;
00440 break;
00441 case NORTH_WEST:
00442 return SOUTH_EAST;
00443 break;
00444 case NORTH_EAST:
00445 return SOUTH_WEST;
00446 break;
00447 case SOUTH_WEST:
00448 return NORTH_EAST;
00449 break;
00450 case SOUTH_EAST:
00451 return NORTH_WEST;
00452 break;
00453 }
00454 return LEFT;
00455 }
00456
00457 string Util::get(MSettings *settings, string key) {
00458 MSettings::iterator it = settings->find(key);
00459 return (it != settings->end()) ? (*it).second : "";
00460 }
00461
00462 void Util::remove(MSettings *settings, string prefix) {
00463
00464 unsigned int length = prefix.length();
00465 for (MSettings::iterator it = settings->begin();
00466 it != settings->end(); it++)
00467 {
00468 string key = (*it).first;
00469 if (key.length() >= length) {
00470 if (key.substr(0, length) == prefix) {
00471 settings->erase(it);
00472 }
00473 }
00474 }
00475 }
00476
00477 Action *Util::get(MBindings *bindings, string key) {
00478 MBindings::iterator it = bindings->find(key);
00479 return (it != bindings->end()) ? (*it).second : 0;
00480 }
00481
00482 void Util::remove(MBindings *bindings, string prefix) {
00483
00484 unsigned int length = prefix.length();
00485 for (MBindings::iterator it = bindings->begin();
00486 it != bindings->end(); it++)
00487 {
00488 string key = (*it).first;
00489 if (key.length() >= length) {
00490 if (key.substr(0, length) == prefix) {
00491 bindings->erase(it);
00492 }
00493 }
00494 }
00495 }