diff options
author | rathnor <rathnor> | 2003-06-12 15:12:19 (GMT) |
---|---|---|
committer | rathnor <rathnor> | 2003-06-12 15:12:19 (GMT) |
commit | e139cbb0283f7480fc26c58dc3f8a48e69011eab (patch) | |
tree | 2058a848943cb008dfe17270ad49853747212481 /src/Remember.cc | |
parent | 94f1c164161e8faaf064d8b7cdfe36c9ca978055 (diff) | |
download | fluxbox-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.cc | 199 |
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 | ||
128 | std::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 | ||
155 | Application::Application() { | 131 | Application::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 | |||
168 | Remember::Remember() { | 148 | Remember::Remember() { |
169 | load(); | 149 | load(); |
170 | } | 150 | } |
171 | 151 | ||
172 | Application* Remember::add(const char* app_name) { | 152 | Remember::~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 | ||
180 | Application* Remember::find(WinClient &winclient) { | 166 | Application* 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); | |
184 | Application* 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 | 185 | Application * Remember::add(WinClient &winclient) { | |
189 | Application* 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 | ||
199 | int Remember::parseApp(ifstream &file, Application &app) { | 196 | int 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) { | |||
623 | void Remember::updateWindowClose(FluxboxWindow &win) { | 614 | void 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 | } |