aboutsummaryrefslogtreecommitdiff
path: root/src/Remember.cc
diff options
context:
space:
mode:
authorrathnor <rathnor>2003-06-12 15:12:19 (GMT)
committerrathnor <rathnor>2003-06-12 15:12:19 (GMT)
commite139cbb0283f7480fc26c58dc3f8a48e69011eab (patch)
tree2058a848943cb008dfe17270ad49853747212481 /src/Remember.cc
parent94f1c164161e8faaf064d8b7cdfe36c9ca978055 (diff)
downloadfluxbox-e139cbb0283f7480fc26c58dc3f8a48e69011eab.zip
fluxbox-e139cbb0283f7480fc26c58dc3f8a48e69011eab.tar.bz2
add regular expression support in remember capabilities
see ChangeLog for details
Diffstat (limited to 'src/Remember.cc')
-rw-r--r--src/Remember.cc199
1 files changed, 89 insertions, 110 deletions
diff --git a/src/Remember.cc b/src/Remember.cc
index 5480d20..a31843b 100644
--- a/src/Remember.cc
+++ b/src/Remember.cc
@@ -21,9 +21,10 @@
21// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22// DEALINGS IN THE SOFTWARE. 22// DEALINGS IN THE SOFTWARE.
23 23
24// $Id: Remember.cc,v 1.23 2003/06/06 14:07:22 rathnor Exp $ 24// $Id: Remember.cc,v 1.24 2003/06/12 15:12:19 rathnor Exp $
25 25
26#include "Remember.hh" 26#include "Remember.hh"
27#include "ClientPattern.hh"
27#include "StringUtil.hh" 28#include "StringUtil.hh"
28#include "Screen.hh" 29#include "Screen.hh"
29#include "Window.hh" 30#include "Window.hh"
@@ -125,32 +126,7 @@ FbTk::Menu *createRememberMenu(Remember &remember, FluxboxWindow &win) {
125 return menu; 126 return menu;
126}; 127};
127 128
128std::string getWMClass(Window w) { 129}; // end anonymous namespace
129 XClassHint ch;
130
131 if (XGetClassHint(FbTk::App::instance()->display(), w, &ch) == 0) {
132 cerr<<"Failed to read class hint!"<<endl;
133 return "";
134 } else {
135 string instance_name;
136 if (ch.res_name != 0) {
137 instance_name = const_cast<char *>(ch.res_name);
138 XFree(ch.res_name);
139 } else
140 instance_name = "";
141
142 if (ch.res_class != 0) {
143 //m_class_name = const_cast<char *>(ch.res_class);
144 XFree(ch.res_class);
145 } else {
146 //m_class_name = "";
147 }
148
149 return instance_name;
150 }
151}
152
153};
154 130
155Application::Application() { 131Application::Application() {
156 workspace_remember = 132 workspace_remember =
@@ -165,35 +141,56 @@ Application::Application() {
165 save_on_close_remember = false; 141 save_on_close_remember = false;
166} 142}
167 143
144/********************************************************
145 * Remember *
146 ************/
147
168Remember::Remember() { 148Remember::Remember() {
169 load(); 149 load();
170} 150}
171 151
172Application* Remember::add(const char* app_name) { 152Remember::~Remember() {
173 if (!app_name) 153 // free our resources
174 return 0; 154
175 Application* a = new Application(); 155 // the patterns free the "Application"s
176 apps[app_name] = a; 156 // the client mapping shouldn't need cleaning
177 return a; 157 Patterns::iterator it;
158 while (!m_pats.empty()) {
159 it = m_pats.begin();
160 delete it->first; // ClientPattern
161 delete it->second; // Application
162 m_pats.erase(it);
163 }
178} 164}
179 165
180Application* Remember::find(WinClient &winclient) { 166Application* Remember::find(WinClient &winclient) {
181 return find(getWMClass(winclient.window()).c_str()); 167 // if it is already associated with a application, return that one
182} 168 // otherwise, check it against every pattern that we've got
183 169 Clients::iterator wc_it = m_clients.find(&winclient);
184Application* Remember::add(WinClient &winclient) { 170 if (wc_it != m_clients.end())
185 return add(getWMClass(winclient.window()).c_str()); 171 return wc_it->second;
172 else {
173 Patterns::iterator it = m_pats.begin();
174 for (; it != m_pats.end(); it++)
175 if (it->first->match(winclient)) {
176 it->first->addMatch();
177 m_clients[&winclient] = it->second;
178 return it->second;
179 }
180 }
181 // oh well, no matches
182 return 0;
186} 183}
187 184
188 185Application * Remember::add(WinClient &winclient) {
189Application* Remember::find(const char* app_name) { 186 ClientPattern *p = new ClientPattern();
190 if (!app_name) 187 Application *app = new Application();
191 return 0; 188 // by default, we match against the WMClass of a window.
192 Apps::iterator i = apps.find(app_name); 189 p->addTerm(p->getProperty(ClientPattern::NAME, winclient), ClientPattern::NAME);
193 if (i != apps.end()) 190 m_clients[&winclient] = app;
194 return i->second; 191 p->addMatch();
195 else 192 m_pats.push_back(make_pair(p, app));
196 return 0; 193 return app;
197} 194}
198 195
199int Remember::parseApp(ifstream &file, Application &app) { 196int Remember::parseApp(ifstream &file, Application &app) {
@@ -315,31 +312,24 @@ void Remember::load() {
315 if (line[0] == '#') 312 if (line[0] == '#')
316 continue; 313 continue;
317 string key; 314 string key;
318 int pos=0; 315 int err=0;
319 int err = FbTk::StringUtil::getStringBetween(key, 316 int pos = FbTk::StringUtil::getStringBetween(key,
320 line.c_str(), 317 line.c_str(),
321 '[', ']'); 318 '[', ']');
322 319
323 if (err > 0 && key == "app") { 320 if (pos > 0 && key == "app") {
324 pos += err; 321 ClientPattern *pat = new ClientPattern(line.c_str() + pos);
325 string label; 322 if ((err = pat->error()) == 0) {
326 err = FbTk::StringUtil::getStringBetween(label, 323 Application *app = new Application();
327 line.c_str()+pos, 324 m_pats.push_back(make_pair(pat, app));
328 '(', ')');
329 if (err>0) {
330 Application *app = 0;
331 Apps::iterator i = apps.find(label);
332 if (i == apps.end()) {
333 app = new Application();
334 apps[label] = app;
335 } else
336 app = i->second;
337 row += parseApp(apps_file, *app); 325 row += parseApp(apps_file, *app);
338 } else 326 } else {
339 cerr<<"Error1 in apps file. Line("<<row<<")"<<endl; 327 cerr<<"Error reading apps file at line "<<row<<", column "<<(err+pos)<<"."<<endl;
328 delete pat; // since it didn't work
329 }
340 } else 330 } else
341 cerr<<"Error2 in apps file. Line("<<row<<")"<<endl; 331 cerr<<"Error in apps file on line "<<row<<"."<<endl;
342 332
343 } 333 }
344 } else { 334 } else {
345#ifdef DEBUG 335#ifdef DEBUG
@@ -358,28 +348,28 @@ void Remember::save() {
358 string apps_string; 348 string apps_string;
359 Fluxbox::instance()->getDefaultDataFilename("apps", apps_string); 349 Fluxbox::instance()->getDefaultDataFilename("apps", apps_string);
360 ofstream apps_file(apps_string.c_str()); 350 ofstream apps_file(apps_string.c_str());
361 Apps::iterator it = apps.begin(); 351 Patterns::iterator it = m_pats.begin();
362 Apps::iterator it_end = apps.end(); 352 Patterns::iterator it_end = m_pats.end();
363 for (; it != it_end; ++it) { 353 for (; it != it_end; ++it) {
364 apps_file << "[app] (" << it->first << ")" << endl; 354 apps_file << "[app]"<<it->first->toString()<<endl;
365 Application *a = it->second; 355 Application &a = *it->second;
366 if (a->workspace_remember) { 356 if (a.workspace_remember) {
367 apps_file << " [Workspace]\t{" << a->workspace << "}" << endl; 357 apps_file << " [Workspace]\t{" << a.workspace << "}" << endl;
368 } 358 }
369 if (a->dimensions_remember) { 359 if (a.dimensions_remember) {
370 apps_file << " [Dimensions]\t{" << a->w << " " << a->h << "}" << endl; 360 apps_file << " [Dimensions]\t{" << a.w << " " << a.h << "}" << endl;
371 } 361 }
372 if (a->position_remember) { 362 if (a.position_remember) {
373 apps_file << " [Position]\t{" << a->x << " " << a->y << "}" << endl; 363 apps_file << " [Position]\t{" << a.x << " " << a.y << "}" << endl;
374 } 364 }
375 if (a->shadedstate_remember) { 365 if (a.shadedstate_remember) {
376 apps_file << " [Shaded]\t{" << ((a->shadedstate)?"yes":"no") << "}" << endl; 366 apps_file << " [Shaded]\t{" << ((a.shadedstate)?"yes":"no") << "}" << endl;
377 } 367 }
378 if (a->tabstate_remember) { 368 if (a.tabstate_remember) {
379 apps_file << " [Tab]\t\t{" << ((a->tabstate)?"yes":"no") << "}" << endl; 369 apps_file << " [Tab]\t\t{" << ((a.tabstate)?"yes":"no") << "}" << endl;
380 } 370 }
381 if (a->decostate_remember) { 371 if (a.decostate_remember) {
382 switch (a->decostate) { 372 switch (a.decostate) {
383 case (0) : 373 case (0) :
384 apps_file << " [Deco]\t{NONE}" << endl; 374 apps_file << " [Deco]\t{NONE}" << endl;
385 break; 375 break;
@@ -401,21 +391,21 @@ void Remember::save() {
401 apps_file << " [Deco]\t{BORDER}" << endl; 391 apps_file << " [Deco]\t{BORDER}" << endl;
402 break; 392 break;
403 default: 393 default:
404 apps_file << " [Deco]\t{0x"<<hex<<a->decostate<<dec<<"}"<<endl; 394 apps_file << " [Deco]\t{0x"<<hex<<a.decostate<<dec<<"}"<<endl;
405 break; 395 break;
406 } 396 }
407 } 397 }
408 if (a->stuckstate_remember) { 398 if (a.stuckstate_remember) {
409 apps_file << " [Sticky]\t{" << ((a->stuckstate)?"yes":"no") << "}" << endl; 399 apps_file << " [Sticky]\t{" << ((a.stuckstate)?"yes":"no") << "}" << endl;
410 } 400 }
411 if (a->jumpworkspace_remember) { 401 if (a.jumpworkspace_remember) {
412 apps_file << " [Jump]\t{" << ((a->jumpworkspace)?"yes":"no") << "}" << endl; 402 apps_file << " [Jump]\t{" << ((a.jumpworkspace)?"yes":"no") << "}" << endl;
413 } 403 }
414 if (a->layer_remember) { 404 if (a.layer_remember) {
415 apps_file << " [Layer]\t{" << a->layer << "}" << endl; 405 apps_file << " [Layer]\t{" << a.layer << "}" << endl;
416 } 406 }
417 if (a->save_on_close_remember) { 407 if (a.save_on_close_remember) {
418 apps_file << " [Close]\t{" << ((a->save_on_close)?"yes":"no") << "}" << endl; 408 apps_file << " [Close]\t{" << ((a.save_on_close)?"yes":"no") << "}" << endl;
419 } 409 }
420 apps_file << "[end]" << endl; 410 apps_file << "[end]" << endl;
421 } 411 }
@@ -563,6 +553,7 @@ void Remember::setupWindow(FluxboxWindow &win) {
563 if (winclient.transientFor()) { 553 if (winclient.transientFor()) {
564 // still put something in the menu so people don't get confused 554 // still put something in the menu so people don't get confused
565 // so, we add a disabled item... 555 // so, we add a disabled item...
556 // TODO: nls
566 FbTk::MenuItem *item = new FbTk::MenuItem("Remember..."); 557 FbTk::MenuItem *item = new FbTk::MenuItem("Remember...");
567 item->setEnabled(false); 558 item->setEnabled(false);
568 win.menu().insert(item, menupos); 559 win.menu().insert(item, menupos);
@@ -623,10 +614,15 @@ void Remember::setupWindow(FluxboxWindow &win) {
623void Remember::updateWindowClose(FluxboxWindow &win) { 614void Remember::updateWindowClose(FluxboxWindow &win) {
624 // This doesn't work at present since fluxbox.cc is missing the windowclose stuff. 615 // This doesn't work at present since fluxbox.cc is missing the windowclose stuff.
625 // I don't trust it (particularly winClient()) while this is the case 616 // I don't trust it (particularly winClient()) while this is the case
617
626 return; 618 return;
627 619
628 WinClient &winclient = win.winClient(); 620 WinClient &winclient = win.winClient();
629 Application *app = find(winclient); 621 Application *app = find(winclient);
622 Clients::iterator wc_it = m_clients.find(&win.winClient());
623
624 if (wc_it != m_clients.end())
625 m_clients.erase(wc_it);
630 626
631 if (!app || !(app->save_on_close_remember && app->save_on_close)) 627 if (!app || !(app->save_on_close_remember && app->save_on_close))
632 return; 628 return;
@@ -636,23 +632,6 @@ void Remember::updateWindowClose(FluxboxWindow &win) {
636 rememberAttrib(winclient, (Attribute) attrib); 632 rememberAttrib(winclient, (Attribute) attrib);
637 } 633 }
638 } 634 }
639/* 635
640 if (app->workspace_remember)
641 app->rememberWorkspace(win.workspaceNumber());
642 if (app->dimensions_remember)
643 app->rememberDimensions(win.width(), win.height());
644 if (app->position_remember)
645 app->rememberPosition(win.x(), win.y());
646 if (app->shadedstate_remember)
647 app->rememberShadedstate(win.isShaded());
648 // external tabs off atm
649 //if (app->tabstate_remember) ...
650 if (app->decostate_remember)
651 app->rememberDecostate(win.decorationMask());
652 if (app->stuckstate_remember)
653 app->rememberStuckstate(win.isStuck());
654 if (app->jumpworkspace_remember)
655 app->rememberJumpworkspace(true);
656*/
657 save(); 636 save();
658} 637}