trunk 20080912
[gitenigma.git] / src / enigma_plugins.cpp
blob695f443ab866fcece8701107f134633a233f4d6a
1 #include <enigma_plugins.h>
3 #include <config.h>
5 #include <dlfcn.h>
6 #include <dirent.h>
7 #include <unistd.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <fcntl.h>
11 #include <stdio.h>
13 #include <enigma.h>
14 #include <enigma_lcd.h>
15 #include <enigma_main.h>
16 #include <lib/base/eerror.h>
17 #include <lib/gdi/lcd.h>
18 #include <lib/gdi/font.h>
19 #include <lib/gdi/grc.h>
20 #include <lib/driver/rc.h>
21 #include <lib/driver/streamwd.h>
22 #include <lib/dvb/edvb.h>
23 #include <lib/dvb/decoder.h>
24 #include <lib/gui/eskin.h>
25 #include <lib/gui/eprogress.h>
26 #include <lib/system/info.h>
28 ePluginThread *ePluginThread::instance = NULL;
30 ePlugin::ePlugin(eListBox<ePlugin> *parent, const char *cfgfile, eSimpleConfigFile &config, const char* descr)
31 : eListBoxEntryText((eListBox<eListBoxEntryText>*)parent)
33 eDebug(cfgfile);
35 name = text = config.getInfo("name");
37 if (text.isNull())
38 text="(" + eString(cfgfile) + " is invalid)";
40 desc = config.getInfo("desc");
42 if (desc)
44 helptext = desc;
47 depend = config.getInfo("depend");
48 cfgname = cfgfile;
49 requires = config.getInfo("requires");
50 needfb = atoi(config.getInfo("needfb").c_str());
51 needlcd = atoi(config.getInfo("needlcd").c_str());
52 needrc = atoi(config.getInfo("needrc").c_str());
53 needvtxtpid = atoi(config.getInfo("needvtxtpid").c_str());
54 needoffsets = atoi(config.getInfo("needoffsets").c_str());
55 version = atoi(config.getInfo("pluginversion").c_str());
56 type = atoi(config.getInfo("type").c_str());
57 showpig = atoi(config.getInfo("pigon").c_str());
59 if (type == eZapPlugins::ScriptPlugin)
60 sopath = eString(cfgfile).left(strlen(cfgfile) - 4) + ".sh";
61 else
62 sopath = eString(cfgfile).left(strlen(cfgfile) - 4) + ".so";
64 pluginname = eString(cfgfile).mid(eString(cfgfile).rfind('/') + 1);
66 pluginname = pluginname.left(pluginname.length() - 4);
67 sortpos = 10000;
68 eConfig::getInstance()->getKey(eString().sprintf("/enigma/plugins/sortpos/%s",pluginname.c_str()).c_str(), sortpos);
72 ePluginContextMenu::ePluginContextMenu(ePlugin* current_plugin, int reordering)
73 : eListBoxWindow<eListBoxEntryMenu>(_("Plugin Menu"), 6, 400, true)
75 init_ePluginContextMenu(current_plugin, reordering);
77 void ePluginContextMenu::init_ePluginContextMenu(ePlugin* current_plugin, int reordering)
79 eListBoxEntry *prev=0;
81 move(ePoint(150, 80));
82 if ( reordering )
83 prev = new eListBoxEntryMenu(&list, _("disable move mode"), _("switch move mode off"), 0, (void*)1);
84 else
85 prev = new eListBoxEntryMenu(&list, _("enable move mode"), _("activate mode to simply change the entry order"), 0, (void*)1);
86 struct stat64 s;
87 if (!::stat64(current_plugin->cfgname.c_str(),&s) && ((s.st_mode & S_IWUSR) == S_IWUSR))
89 prev = new eListBoxEntryMenu(&list, _("rename"), _("rename the selected plugin"), 0,(void*)2);
91 new eListBoxEntryMenuSeparator(&list, eSkin::getActive()->queryImage("listbox.separator"), 0, true );
92 int ColorButtonsFirst=0;
93 eConfig::getInstance()->getKey("/enigma/plugins/colorbuttonsfirst", ColorButtonsFirst);
94 if (ColorButtonsFirst)
95 prev = new eListBoxEntryMenu(&list, _("number buttons first"), _("use number buttons as first shortcuts"),0,(void*)3);
96 else
97 prev = new eListBoxEntryMenu(&list, _("color buttons first"), _("use color buttons as first shortcuts"),0,(void*)3);
98 list.setFlags(eListBoxBase::flagHasShortcuts);
99 CONNECT(list.selected, ePluginContextMenu::entrySelected);
102 void ePluginContextMenu::entrySelected(eListBoxEntryMenu *test)
104 if (!test)
105 close(0);
106 else
107 close((int)test->getKey());
110 const char *eZapPlugins::PluginPath[] = { "/var/tuxbox/plugins/", PLUGINDIR "/", "" };
112 eZapPlugins::eZapPlugins(Types type, eWidget* lcdTitle, eWidget* lcdElement)
113 :eListBoxWindow<ePlugin>(type == StandardPlugin ? _("Plugins") : _("Games"), 8, 400,true), type(type),reordering(0)
115 setHelpText(_("select plugin and press ok"));
116 #ifndef DISABLE_LCD
117 setLCD(lcdTitle, lcdElement);
118 #endif
119 list.setFlags(eListBoxBase::flagHasShortcuts);
120 int ColorButtonsFirst=0;
121 eConfig::getInstance()->getKey("/enigma/plugins/colorbuttonsfirst", ColorButtonsFirst);
122 if (ColorButtonsFirst)
123 list.setFlags(eListBoxBase::flagColorShortcutsFirst);
124 CONNECT(list.selected, eZapPlugins::selected);
125 valign();
128 int eZapPlugins::listPlugins(Types type, std::vector<eString> &list)
130 int cnt = 0;
131 for (int i = 0; i < 2; i++)
133 DIR *d = opendir(PluginPath[i]);
134 if (!d)
136 continue;
138 while (struct dirent *e = readdir(d))
140 eString FileName = e->d_name;
141 if (FileName.find(".cfg") == FileName.size() - 4)
143 eString cfgname = (eString(PluginPath[i]) + FileName).c_str();
144 eSimpleConfigFile config(cfgname.c_str());
145 if (atoi(config.getInfo("type").c_str()) == (int)type)
147 list.push_back(cfgname);
148 ++cnt;
152 closedir(d);
154 return cnt;
157 int eZapPlugins::getAutostartPlugins(std::vector<eString> &list)
159 int cnt = listPlugins(AutostartPlugin, list);
160 for (unsigned int i = 0; i < list.size(); i++)
162 list[i] = list[i].left(list[i].length() - 4) + ".so";
164 return cnt;
167 int eZapPlugins::getFileExtensionPlugins(std::vector<FileExtensionScriptInfo> &list)
169 std::vector<eString> cfgfilelist;
170 int cnt = listPlugins(FileExtensionScriptPlugin, cfgfilelist);
171 for (unsigned int i = 0; i < cfgfilelist.size(); i++)
173 FileExtensionScriptInfo info;
174 eSimpleConfigFile config(cfgfilelist[i].c_str());
175 info.file_pattern = config.getInfo("pattern");
176 info.directory_pattern = config.getInfo("dirpattern");
177 info.needfb = atoi(config.getInfo("needfb").c_str());
178 info.needrc = atoi(config.getInfo("needrc").c_str());
179 info.needlcd = atoi(config.getInfo("needlcd").c_str());
180 info.command = config.getInfo("command");
181 list.push_back(info);
183 return cnt;
186 int eZapPlugins::find(bool ignore_requires)
188 int cnt=0;
189 ePlugin *plg=0;
190 std::set<eString> exist;
191 int connType=0;
192 eConfig::getInstance()->getKey("/elitedvb/network/connectionType", connType);
193 bool hasNetwork = eSystemInfo::getInstance()->hasNetwork();
196 for ( int i = 0; i < 2; i++ )
198 DIR *d=opendir(PluginPath[i]);
199 if (!d)
201 eString err;
202 err.sprintf(_("Couldn't read plugin directory %s"), PluginPath[i]);
203 eDebug(err.c_str());
204 if ( i )
206 eMessageBox msg(err, _("Error"), eMessageBox::iconError|eMessageBox::btOK );
207 msg.show();
208 msg.exec();
209 msg.hide();
210 return -1;
212 continue;
214 while (struct dirent *e=readdir(d))
216 eString FileName = e->d_name;
217 if (FileName.find(".cfg") == FileName.size() - 4)
219 eString cfgname = (eString(PluginPath[i]) + FileName).c_str();
220 eSimpleConfigFile config(cfgname.c_str());
222 int current_type = (Types)atoi(config.getInfo("type").c_str());
224 //Scripts should be treated as normal plugins in this context
225 if (current_type == ScriptPlugin)
226 current_type = StandardPlugin;
228 if ((type == AnyPlugin) || (type == current_type))
230 // do not add existing plugins twice
231 if (exist.find(FileName) != exist.end())
232 continue;
234 exist.insert(FileName);
235 // check for required specifications
236 eString requires = config.getInfo("requires");
237 if (!ignore_requires)
239 if ((!hasNetwork) && (requires.find("network") != eString::npos))
240 continue;
241 if ((!connType) && (requires.find("dsl") != eString::npos))
242 continue;
244 plg = new ePlugin(&list, cfgname.c_str(), config);
245 ++cnt;
249 closedir(d);
251 list.sort();
252 return cnt;
255 int eZapPlugins::execSelectPrevious(eString &previous)
257 int cnt=0;
258 int res = 0;
260 previousPlugin = previous;
262 cnt = find();
263 if ((type == StandardPlugin) && (cnt == GamePlugin))
265 selected(list.getFirst());
267 else
269 ePlugin *it = list.getFirst();
270 list.setCurrent(it);
271 if (!it) return res;
272 while (it->pluginname != previous)
274 it = list.goNext();
275 if (it == list.getFirst()) break;
277 list.setCurrent(it);
278 show();
279 res=eListBoxWindow<ePlugin>::exec();
280 hide();
282 previous = previousPlugin;
283 return res;
286 int eZapPlugins::exec()
288 int cnt=0;
289 int res = 0;
291 cnt = find();
292 if ((type == StandardPlugin) && (cnt == GamePlugin))
294 selected(list.getFirst());
295 } else {
296 list.setCurrent(list.getFirst());
297 show();
298 res=eListBoxWindow<ePlugin>::exec();
299 hide();
301 return res;
304 eString eZapPlugins::execPluginByName(const char* name, bool onlySearch)
306 if ( name )
308 eString Path;
309 for ( int i = 0; i < 3; i++ )
311 Path=PluginPath[i];
312 Path+=name;
313 FILE *fp=fopen(Path.c_str(), "rb");
314 if ( fp )
316 fclose(fp);
317 eSimpleConfigFile config(Path.c_str());
318 ePlugin p(0, Path.c_str(), config);
319 if (ePluginThread::getInstance())
321 eDebug("currently one plugin is running.. dont start another one!!");
322 return _("E: currently another plugin is running...");
324 if ( !onlySearch )
325 execPlugin(&p);
326 return "OK";
328 else if ( i == 2)
329 return eString().sprintf(_("plugin '%s' not found"), name );
332 return _("E: no name given");
335 void eZapPlugins::execPlugin(ePlugin* plugin)
337 if (plugin->type == ScriptPlugin)
339 //The current plugin is a script
340 if ((access(plugin->sopath.c_str(), X_OK) == 0))
342 hide();
343 eScriptOutputWindow wnd(plugin);
344 wnd.show();
345 wnd.exec();
346 wnd.hide();
347 show();
349 else
351 eDebug("can't execute %s",plugin->sopath.c_str());
352 eMessageBox mbox(eString().sprintf(_("Cannot execute %s (check rights)"), plugin->sopath.c_str()), (_("Error")), eMessageBox::iconError | eMessageBox::btOK, eMessageBox::btOK, 5);
353 mbox.show();
354 mbox.exec();
355 mbox.hide();
358 else
360 ePluginThread *p = new ePluginThread(plugin, PluginPath, in_loop?this:0);
361 p->start();
364 class eSetPluginSortOrder
366 int n;
367 public:
368 eSetPluginSortOrder(): n(0) { }
369 bool operator()(ePlugin &e)
371 e.sortpos = ++n;
372 eConfig::getInstance()->setKey(eString().sprintf("/enigma/plugins/sortpos/%s",e.pluginname.c_str()).c_str(), e.sortpos);
373 return 0;
377 void eZapPlugins::selected(ePlugin *plugin)
379 switch (reordering)
381 case 1:
382 list.setMoveMode(1);
383 list.setActiveColor(eSkin::getActive()->queryColor("eServiceSelector.entrySelectedToMove"),gColor(0));
384 reordering = 2;
385 return;
386 case 2:
387 list.setMoveMode(0);
388 list.setActiveColor(selectedBackColor,gColor(0));
389 reordering = 1;
390 list.forEachEntry(eSetPluginSortOrder());
391 return;
394 if (!plugin || !plugin->pluginname )
396 close(0);
397 return;
399 execPlugin(plugin);
400 previousPlugin = plugin->pluginname;
402 void eZapPlugins::toggleMoveMode()
404 if (!reordering)
406 selectedBackColor = list.getActiveBackColor();
407 reordering = 1;
409 else
410 reordering= 0;
412 void eZapPlugins::renamePlugin()
414 ePlugin* plugin = (ePlugin*)list.getCurrent();
415 eSimpleConfigFile config(plugin->cfgname.c_str());
416 TextEditWindow wnd(_("Enter new name for the plugin:"));
417 wnd.setText(_("Rename plugin"));
418 wnd.show();
419 wnd.setEditText(config.getInfo("name"));
420 int ret = wnd.exec();
421 wnd.hide();
422 if ( !ret && config.getInfo("name") != wnd.getEditText())
424 config.setInfo("name",wnd.getEditText().c_str());
425 config.Save(plugin->cfgname.c_str());
426 plugin->SetText(wnd.getEditText());
430 void eZapPlugins::showContextMenu()
432 ePluginContextMenu m((ePlugin*)list.getCurrent(), reordering);
433 hide();
434 m.show();
435 int res=m.exec();
436 m.hide();
437 int ColorButtonsFirst=0;
438 switch (res)
440 case 1: // enable/disable movemode
441 toggleMoveMode();
442 break;
443 case 2: // rename plugin
444 renamePlugin();
445 break;
446 case 3:
447 eConfig::getInstance()->getKey("/enigma/plugins/colorbuttonsfirst", ColorButtonsFirst);
448 ColorButtonsFirst = 1-ColorButtonsFirst;
449 eConfig::getInstance()->setKey("/enigma/plugins/colorbuttonsfirst", ColorButtonsFirst);
450 if (ColorButtonsFirst)
451 list.setFlags(eListBoxBase::flagColorShortcutsFirst);
452 else
453 list.removeFlags(eListBoxBase::flagColorShortcutsFirst);
454 break;
455 default:
456 break;
458 show();
461 int eZapPlugins::eventHandler(const eWidgetEvent &event)
463 switch (event.type)
465 case eWidgetEvent::evtAction:
466 if (list.eventHandlerShortcuts(event))
467 return 1;
468 else if (event.action == &i_cursorActions->cancel)
469 close(0);
470 else if (event.action == &i_shortcutActions->menu)
471 showContextMenu();
472 else
473 break;
474 return 1;
475 default:
476 break;
478 return eWindow::eventHandler(event);
482 PluginParam *ePluginThread::first = NULL, *ePluginThread::tmp = NULL;
484 void ePluginThread::MakeParam(const char * const id, int val)
486 PluginParam* p = new PluginParam;
488 if (tmp)
489 tmp->next = p;
491 p->id = id;
492 char buf[10];
493 sprintf(buf, "%i", val);
494 p->val = new char[strlen(buf)+1];
495 strcpy(p->val, buf);
497 if (!first)
498 first = p;
500 p->next=0;
501 tmp = p;
504 void ePluginThread::start()
506 wasVisible = wnd ? wnd->isVisible() : 0;
508 if (!thread_running())
510 argc=0;
511 eString argv[20];
513 if (depend)
515 char depstring[129];
516 char *p;
517 char *np;
519 strcpy(depstring, depend.c_str());
521 p=depstring;
523 while(p)
525 np=strchr(p,',');
526 if ( np )
527 *np=0;
529 for ( int i=0; i < 3; i++ )
531 eString str;
532 if (np)
533 str.assign( p, np-p );
534 else
535 str.assign( p );
537 FILE *fp=fopen((eString(PluginPath[i])+str).c_str(), "rb");
538 if ( fp )
540 fclose(fp);
541 argv[argc++] = eString(PluginPath[i])+str;
542 break;
545 p=np?np+1:0;
549 argv[argc++]=sopath;
551 int i;
552 eDebug("pluginname is %s %d", pluginname.c_str(), wasVisible);
554 for (i=0; i<argc; i++)
556 eDebug("loading %s" , argv[i].c_str());
557 libhandle[i]=dlopen(argv[i].c_str(), RTLD_GLOBAL|RTLD_NOW);
558 if (!libhandle[i])
560 const char *de=dlerror();
561 eDebug(de);
562 eMessageBox msg(de, "plugin loading failed", eMessageBox::btOK, eMessageBox::btOK, 5 );
563 msg.show();
564 msg.exec();
565 msg.hide();
566 break;
569 if (i<argc) // loading of one dependencie failed... close the other
571 while(i)
572 dlclose(libhandle[--i]);
573 if (wasVisible)
574 wnd->show();
576 else
578 // this is ugly code.. but i have no other idea to detect enigma plugins..
579 bool isEnigmaPlugin=false;
580 int fd = open(sopath.c_str(), O_RDONLY);
581 if ( fd >= 0 )
583 char buf[8192];
584 while(!isEnigmaPlugin)
586 int rd = ::read(fd, buf, 8192);
587 for (int i=0; i < rd-15; ++i )
589 if (!strcmp(buf+i, "_ZN7eWidgetD0Ev"))
590 isEnigmaPlugin=true;
592 if ( rd < 8192 )
593 break;
595 close(fd);
598 eDebug("would exec (%s) plugin %s",
599 isEnigmaPlugin ? "ENIGMA" : "NORMAL",
600 sopath.c_str());
602 PluginExec execPlugin = (PluginExec) dlsym(libhandle[i-1], "plugin_exec");
603 if (!execPlugin)
604 // show messagebox.. and close after 5 seconds...
606 eMessageBox msg("The symbol plugin_exec was not found. sorry.", "plugin executing failed", eMessageBox::btOK, eMessageBox::btOK, 5 );
607 msg.show();
608 msg.exec();
609 msg.hide();
611 else
613 if (needrc)
614 MakeParam(P_ID_RCINPUT, eRCInput::getInstance()->lock());
616 if ( wasVisible )
617 wnd->hide();
619 #ifndef DISABLE_LCD
620 if (needlcd && eSystemInfo::getInstance()->hasLCD())
621 MakeParam(P_ID_LCD, eDBoxLCD::getInstance()->lock() );
622 #endif
624 if (needvtxtpid)
626 if(Decoder::current.tpid==-1)
627 MakeParam(P_ID_VTXTPID, 0);
628 else
629 MakeParam(P_ID_VTXTPID, Decoder::current.tpid);
630 // stop teletext subtitles, if activated
631 eSubtitleWidget *i = eSubtitleWidget::getInstance();
632 if (i) i->stopttx();
633 // stop vtxt reinsertion
634 tpid = Decoder::current.tpid;
635 if (tpid != -1)
637 eDebug("stop vtxt reinsertion");
638 Decoder::parms.tpid=-1;
639 Decoder::Set();
643 if (needfb)
644 MakeParam(P_ID_FBUFFER, fbClass::getInstance()->lock());
646 if (needoffsets)
648 int left=20, top=20, right=699, bottom=555;
649 eConfig::getInstance()->getKey("/enigma/plugins/needoffsets/left", left);
650 eConfig::getInstance()->getKey("/enigma/plugins/needoffsets/top", top);
651 eConfig::getInstance()->getKey("/enigma/plugins/needoffsets/right", right);
652 eConfig::getInstance()->getKey("/enigma/plugins/needoffsets/bottom", bottom);
653 MakeParam(P_ID_OFF_X, left);
654 MakeParam(P_ID_OFF_Y, top);
655 MakeParam(P_ID_END_X, right);
656 MakeParam(P_ID_END_Y, bottom);
659 /* for(PluginParam *par = first; par; par=par->next )
661 printf ("id: %s - val: %s\n", par->id, par->val);
662 printf("%p\n", par->next);
665 if ( isEnigmaPlugin )
667 eDebug("start plugin in current thread");
668 thread();
669 finalize_plugin();
671 else
673 eDebug("start plugin thread...");
674 run(); // start thread
679 else
680 eDebug("don't start plugin.. another one is running");
683 void ePluginThread::thread()
685 if ( thread_running() )
686 eDebug("plugin thread running.. execute plugin now");
687 else
688 eDebug("execute plugin now");
689 PluginExec execPlugin = (PluginExec) dlsym(libhandle[argc-1], "plugin_exec");
690 execPlugin(first);
691 eDebug("execute plugin finished");
694 void ePluginThread::recv_msg(const int &)
696 finalize_plugin();
699 void ePluginThread::thread_finished()
701 message.send(1);
704 void ePluginThread::finalize_plugin()
706 while (argc)
707 dlclose(libhandle[--argc]);
709 while (first) // Parameter Liste freigegeben
711 tmp = first->next;
712 delete [] first->val;
713 delete first;
714 first = tmp;
717 if (needfb)
718 fbClass::getInstance()->unlock();
720 #ifndef DISABLE_LCD
721 if (needlcd && eSystemInfo::getInstance()->hasLCD())
723 eDBoxLCD::getInstance()->unlock();
724 eZapLCD::getInstance()->invalidate();
726 #endif
728 if ( wasVisible )
729 wnd->show();
731 if (needrc)
732 eRCInput::getInstance()->unlock();
734 if (needvtxtpid)
736 // start teletext subtitles, if activated
737 eSubtitleWidget *i = eSubtitleWidget::getInstance();
738 if (i) i->startttx(-1);
739 // start vtxt reinsertion
740 if (tpid != -1 && Decoder::current.tpid == -1)
742 eDebug("restart vtxt reinsertion");
743 Decoder::parms.tpid = tpid;
744 Decoder::Set();
747 delete this;
750 eScriptOutputWindow::eScriptOutputWindow(ePlugin *plugin):
751 eWindow(1)
753 cresize(eSize(580, 420));
755 setText(eString().sprintf(_("Output from %s"), plugin->sopath.c_str()));
757 scrollbar = new eProgress(this);
758 scrollbar->setName("scrollbar");
759 scrollbar->setStart(0);
760 scrollbar->setPerc(100);
761 scrollbar->move(ePoint(width() - 30, 5));
762 scrollbar->resize(eSize(20, height() - 100));
763 scrollbar->setProperty("direction", "1");
765 visible = new eWidget(this);
766 visible->setName("visible");
767 visible->move(ePoint(10, 5));
768 visible->resize(eSize(width() - 40, height() - 100));
770 label = new eLabel(visible);
771 label->setFlags(RS_WRAP);
772 float lineheight = fontRenderClass::getInstance()->getLineHeight(label->getFont());
773 int lines = (int) (visible->getSize().height() / lineheight);
774 pageHeight = (int) (lines * lineheight);
775 visible->resize(eSize(visible->getSize().width(), pageHeight + (int) (lineheight / 6)));
776 label->resize(eSize(visible->getSize().width(), pageHeight * 16));
778 label->hide();
779 label->move(ePoint(0, 0));
780 label->setText(eString().sprintf(_("Executing %s. Please wait..."), plugin->sopath.c_str()));
781 script = new eConsoleAppContainer(plugin->sopath);
782 if (!script->running())
783 label->setText(eString().sprintf(_("Could not execute %s"), plugin->sopath.c_str()));
784 else
786 eDebug("%s started", plugin->sopath.c_str());
787 CONNECT(script->dataAvail, eScriptOutputWindow::getData);
788 CONNECT(script->appClosed, eScriptOutputWindow::scriptClosed);
790 updateScrollbar();
791 label->show();
793 valign();
796 int eScriptOutputWindow::eventHandler(const eWidgetEvent & event)
798 switch (event.type)
800 case eWidgetEvent::evtAction:
801 if (total && event.action == &i_cursorActions->up)
803 ePoint curPos = label->getPosition();
804 if (curPos.y() < 0)
806 label->move(ePoint(curPos.x(), curPos.y() + pageHeight));
807 updateScrollbar();
810 else if (total && event.action == &i_cursorActions->down)
812 ePoint curPos = label->getPosition();
813 if ((total - pageHeight) >= abs(curPos.y() - pageHeight))
815 label->move(ePoint(curPos.x(), curPos.y() - pageHeight));
816 updateScrollbar();
819 else if (event.action == &i_cursorActions->cancel)
820 close(0);
821 else
822 break;
823 return 1;
824 default:
825 break;
827 return eWindow::eventHandler(event);
830 void eScriptOutputWindow::updateScrollbar()
832 total = pageHeight;
833 int pages = 1;
834 while (total < label->getExtend().height())
836 total += pageHeight;
837 pages++;
840 int start = -label->getPosition().y() * 100 / total;
841 int vis = pageHeight * 100 / total;
842 scrollbar->setParams(start, vis);
843 scrollbar->show();
844 if (pages == 1)
845 total = 0;
849 void eScriptOutputWindow::getData(eString str)
851 scriptOutput += str;
854 void eScriptOutputWindow::scriptClosed(int state)
856 if (script)
858 delete script;
859 script = 0;
861 label->hide();
862 label->move(ePoint(0, 0));
863 label->setText(scriptOutput);
864 updateScrollbar();
865 label->show();
866 scriptOutput.clear();
869 eScriptOutputWindow::~eScriptOutputWindow()
871 if (script)
873 if (script->running())
874 script->kill();
875 delete script;
876 script = 0;