/* -------------------------------------------------------------------------- */ /* */ /* [main.C] Testbed for TE framework */ /* */ /* -------------------------------------------------------------------------- */ /* */ /* Copyright (c) 1997,1998 by Lars Doelle */ /* */ /* This file is part of Konsole, an X terminal. */ /* */ /* The material contained in here more or less directly orginates from */ /* kvt, which is copyright (c) 1996 by Matthias Ettrich */ /* */ /* -------------------------------------------------------------------------- */ /*! \class TEDemo \brief Konsole's main program The class TEDemo handles the application level. Mainly, it is responsible for the configuration, taken from several files, from the command line and from the user. It hardly does anything interesting. */ /*FIXME: - All the material in here badly sufferes from the fact that the configuration can originate from many places, so all is duplicated and falls out of service. Especially the command line is badly broken. The sources are: - command line - menu - configuration files - other events (e.g. resizing) We have to find a single-place method to maintain this. Scedule: post kde 1.2 - Controling the widget is currently done by individual attributes. This lead to quite some amount of flicker when a whole bunch of attributes has to be set, e.g. in session swapping. Scedule: post kde 1.2 - The schema file name in session config files is not location transparent. */ /* TODO - don't reread the pixmap every time */ #include"config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "main.h" #define HERE printf("%s(%d): here\n",__FILE__,__LINE__) #undef PACKAGE #undef VERSION #define PACKAGE "konsole" #define VERSION "0.9.11" #define WITH_VGA const char *fonts[] = {"6x13", "5x7", "6x10", "7x13", "9x15", "10x20", "linux8x16", "linux8x8" }; static QIntDict no2session; static QPtrDict session2no; static int session_no = 0; static QIntDict no2command; static int cmd_serial = 0; TEDemo::TEDemo(const QString& name, QStrList & _args, int login_shell) : KTMainWindow(name), args(_args) { se = 0L; rootxpm = 0L; menubar = menuBar(); setMinimumSize(200,100); // session management setUnsavedData( true ); // terminals cannot store their contents // create terminal emulation framework //////////////////////////////////// te = new TEWidget(this); te->setMinimumSize(150,70); // allow resizing, cause resize in TEWidget // Transparency routines want to know when te change size ... connect ( te, SIGNAL( changedImageSizeSignal(int,int)), SLOT( teChangedSize(int,int)) ); // ... and when user change desktop (Antonio) connect((KWMModuleApplication *)kapp, SIGNAL(desktopChange(int)), SLOT(desktopChange(int))); // create applications ///////////////////////////////////////////////////// setView(te,FALSE); makeMenu(); makeStatusbar(); // Init DnD //////////////////////////////////////////////////////////////// setAcceptDrops(true); // load session commands /////////////////////////////////////////////////// loadSessionCommands(); m_file->insertSeparator(); m_file->insertItem( i18n("E&xit"), kapp, SLOT(quit())); // load schema ///////////////////////////////////////////////////////////// curr_schema = 0; ColorSchema::loadAllSchemas(); for (int i = 0; i < ColorSchema::count(); i++) { ColorSchema* s = ColorSchema::find(i); assert( s ); m_schema->insertItem(s->title.data(),s->numb); } //FIXME: we should build a complete session before running it. // set global options /////////////////////////////////////////////////////// if (b_menuvis) menubar->show(); else menubar->hide(); te->setFrameStyle( b_framevis ? QFrame::WinPanel | QFrame::Sunken : QFrame::NoFrame ); te->setScrollbarLocation(n_scroll); // construct initial session /////////////////////////////////////////////// TESession* initial = new TESession(this,te,args,"xterm",login_shell); title = (args.count() && (kapp->getCaption() == PACKAGE)) ? QString(args.at(0)) // program executed in the title bar : kapp->getCaption(); // `konsole' or -caption initial->setTitle(title); addSession(initial); // read and apply default values /////////////////////////////////////////// readProperties(kapp->getConfig()); // activate and run first session ////////////////////////////////////////// runSession(initial); } /*! sets application window to a size based on columns X lines of the te guest widget. Call with (0,0) for setting default size. */ void TEDemo::setColLin(int columns, int lines) { if (columns==0 && lines==0) { if (defaultSize.isNull()) // not in config file : set default value { defaultSize = te->calcSize(80,24); notifySize(24,80); // set menu items (strange arg order !) } resize(defaultSize); } else { resize(te->calcSize(columns,lines)); notifySize(lines,columns); // set menu items (strange arg order !) } updateRects(); } TEDemo::~TEDemo() { //FIXME: close all session properly and clean up } /* ------------------------------------------------------------------------- */ /* Drag & Drop */ /* */ /* ------------------------------------------------------------------------- */ void TEDemo::dragEnterEvent(QDragEnterEvent* e) { e->accept(QTextDrag::canDecode(e) || QUriDrag::canDecode(e)); } void TEDemo::dropEvent(QDropEvent* event) { // The current behaviour when url(s) are dropped is // * if there is only ONE url and if it's a LOCAL one, ask for paste or cd // * in all other cases, just paste // (for non-local ones, or for a list of URLs, 'cd' is nonsense) QStrList strlist; KURL *url; int file_count = 0; dropText = ""; bool bPopup = true; if(QUriDrag::decode(event, strlist)) { if (strlist.count()) { for(const char* p = strlist.first(); p; p = strlist.next()) { if(file_count++ > 0) { dropText += " "; bPopup = false; // more than one file, don't popup } url = new KURL( QString(p) ); if (url->isLocalFile()) { dropText += url->path(); // local URL : remove protocol } else { dropText += p; bPopup = false; // a non-local file, don't popup } delete url; p = strlist.next(); } if (bPopup) m_drop->popup(pos() + event->pos()); else se->getEmulation()->sendString(dropText.latin1()); } } else if(QTextDrag::decode(event, dropText)) se->getEmulation()->sendString(dropText.latin1()); // Paste it } void TEDemo::drop_menu_activated(int item) { switch (item) { case 0: // paste se->getEmulation()->sendString(dropText.data()); // KWM::activate((Window)this->winId()); break; case 1: // cd ... se->getEmulation()->sendString("cd "); KURL url( dropText ); se->getEmulation()->sendString(url.directory()); se->getEmulation()->sendString("\n"); // KWM::activate((Window)this->winId()); break; } } /* ------------------------------------------------------------------------- */ /* */ /* */ /* ------------------------------------------------------------------------- */ void TEDemo::configureRequest(TEWidget* te, int state, int x, int y) { //printf("TEDemo::configureRequest(_,%d,%d)\n",x,y); ( (state & ShiftButton ) ? m_sessions : (state & ControlButton) ? m_file : m_options ) ->popup(te->mapToGlobal(QPoint(x,y))); } /* ------------------------------------------------------------------------- */ /* */ /* */ /* ------------------------------------------------------------------------- */ void TEDemo::makeStatusbar() { //statusbar = new KStatusBar(this); //setStatusBar(statusbar); } /* ------------------------------------------------------------------------- */ /* */ /* */ /* ------------------------------------------------------------------------- */ void TEDemo::makeMenu() { // options (taken from kvt) ////////////////////////////////////// //m_commands = new QPopupMenu; //connect(m_commands, SIGNAL(activated(int)), SLOT(newSession(int))); m_sessions = new QPopupMenu; m_sessions->setCheckable(TRUE); connect(m_sessions, SIGNAL(activated(int)), SLOT(activateSession(int))); m_file = new QPopupMenu; connect(m_file, SIGNAL(activated(int)), SLOT(newSession(int))); m_font = new QPopupMenu; m_font->setCheckable(TRUE); m_font->insertItem( i18n("&Normal"), 0); m_font->insertSeparator(); //m_font->insertItem( i18n("&Tiny"), 1); m_font->insertItem( i18n("&Small"), 2); m_font->insertItem( i18n("&Medium"), 3); m_font->insertItem( i18n("&Large"), 4); m_font->insertItem( i18n("&Huge"), 5); m_font->insertSeparator(); m_font->insertItem( i18n("&Linux"), 6); m_font->insertItem( i18n("Linux (small)"),7); #ifdef ANY_FONT m_font->insertSeparator(); m_font->insertItem( i18n("&More ..."), 1000); // for other fonts #endif connect(m_font, SIGNAL(activated(int)), SLOT(font_menu_activated(int))); m_scrollbar = new QPopupMenu; m_scrollbar->setCheckable(TRUE); m_scrollbar->insertItem( i18n("&Hide"), SCRNONE); m_scrollbar->insertItem( i18n("&Left"), SCRLEFT); m_scrollbar->insertItem( i18n("&Right"), SCRRIGHT); connect(m_scrollbar, SIGNAL(activated(int)), SLOT(scrollbar_menu_activated(int))); m_size = new QPopupMenu; m_size->setCheckable(TRUE); m_size->insertItem( i18n("40x15 (&small)"), 0); m_size->insertItem( i18n("80x24 (&vt100)"), 1); m_size->insertItem( i18n("80x25 (&ibmpc)"), 2); m_size->insertItem( i18n("80x40 (&xterm)"), 3); m_size->insertItem( i18n("80x52 (ibmv&ga)"), 4); connect(m_size, SIGNAL(activated(int)), SLOT(size_menu_activated(int))); m_schema = new QPopupMenu; m_schema->setCheckable(TRUE); connect(m_schema, SIGNAL(activated(int)), SLOT(schema_menu_activated(int))); m_options = new QPopupMenu; m_options->setCheckable(TRUE); m_options->insertItem( i18n("&Menubar"), 1 ); m_options->insertItem( i18n("&Frame"), 2 ); m_options->insertItem( i18n("Scroll&bar"), m_scrollbar); m_options->insertSeparator(); m_options->insertItem( i18n("BS sends &DEL"), 4 ); m_options->setItemChecked(4,b_bshack); m_options->insertSeparator(); m_options->insertItem( i18n("&Font"), m_font); m_options->insertItem( i18n("&Size"), m_size); m_options->insertItem( i18n("&Schema"), m_schema); m_options->insertSeparator(); m_options->insertItem( i18n("&Save options"), 8); connect(m_options, SIGNAL(activated(int)), SLOT(opt_menu_activated(int))); QPopupMenu* m_help = new QPopupMenu; m_help->insertItem( i18n("&About ..."), this, SLOT(about())); m_help->insertItem( i18n("&User's Manual ..."), this, SLOT(help())); m_help->insertItem( i18n("&Technical Reference ..."), this, SLOT(tecRef())); m_drop = new QPopupMenu; m_drop->insertItem( i18n("Paste"), 0); m_drop->insertItem( i18n("cd"), 1); connect(m_drop, SIGNAL(activated(int)), SLOT(drop_menu_activated(int))); m_options->installEventFilter( this ); // For those who would like to add shortcuts here, be aware that // ALT-key combinations are heavily used by many programs. Thus, // activating shortcuts here means deactivating them in the other // programs. menubar->insertItem(i18n("File") , m_file); //menubar->insertItem(i18n("New"), m_commands); menubar->insertItem(i18n("Sessions"), m_sessions); menubar->insertItem(i18n("Options"), m_options); menubar->insertSeparator(); menubar->insertItem(i18n("Help"), m_help); } /* ------------------------------------------------------------------------- */ /* */ /* Configuration */ /* */ /* ------------------------------------------------------------------------- */ void TEDemo::saveProperties(KConfig* config) { config->setGroup("options"); // bad! will no allow us to support multi windows config->writeEntry("menubar visible",b_menuvis); config->writeEntry("has frame",b_framevis); config->writeEntry("BS hack",b_bshack); config->writeEntry("font",n_font); config->writeEntry("schema",s_schema); config->writeEntry("scrollbar",n_scroll); if (args.count() > 0) config->writeEntry("konsolearguments", args); config->writeEntry("class",name()); config->writeEntry("defaultheight", height()); // for "save options". Not used by SM. config->writeEntry("defaultwidth", width()); // for "save options". Not used by SM. config->writeEntry("kmenubar", //FIXME:Float menubar->menuBarPos() == KMenuBar::Bottom ? "bottom" : "top"); // geometry (placement) done by KTMainWindow config->sync(); } // Called by constructor (with config = kapp->getConfig()) // and by session-management (with config = sessionconfig). // So it has to apply the settings when reading them. void TEDemo::readProperties(KConfig* config) { config->setGroup("options"); // bad! will no allow us to support multi windows /*FIXME: (merging) state of material below unclear.*/ b_menuvis = config->readBoolEntry("menubar visible",TRUE); b_framevis = config->readBoolEntry("has frame",TRUE); b_bshack = config->readBoolEntry("BS hack",TRUE); n_font = QMIN(config->readUnsignedNumEntry("font",3),7); n_scroll = QMIN(config->readUnsignedNumEntry("scrollbar",SCRRIGHT),2); s_schema = config->readEntry("schema",""); // Global options /////////////////////// setMenuVisible(config->readBoolEntry("menubar visible",TRUE)); setFrameVisible(config->readBoolEntry("has frame",TRUE)); scrollbar_menu_activated(QMIN(config->readUnsignedNumEntry("scrollbar",SCRRIGHT),2)); // not necessary for SM (KTMainWindow does it after), but useful for default settings /*FIXME: (merging) state of material below unclear*/ if (menubar->menuBarPos() != KMenuBar::Floating) { QString entry = config->readEntry("kmenubar"); if (!entry.isEmpty() && entry == "floating") { menubar->setMenuBarPos(KMenuBar::Floating); QString geo = config->readEntry("kmenubargeometry"); if (!geo.isEmpty()) menubar->setGeometry(KWM::setProperties(menubar->winId(), geo)); } else if (!entry.isEmpty() && entry == "top") menubar->setMenuBarPos(KMenuBar::Top); else if (!entry.isEmpty() && entry == "bottom") menubar->setMenuBarPos(KMenuBar::Bottom); } // (geometry stuff removed) done by KTMainWindow for SM, and not needed otherwise // Options that should be applied to all sessions ///////////// // (1) set menu items and TEDemo members setBsHack(config->readBoolEntry("BS hack",TRUE)); setFont(QMIN(config->readUnsignedNumEntry("font",3),7)); // sets n_font and menu item setSchema(config->readEntry("schema","")); // (2) apply to sessions (currently only the 1st one) TESession* s = no2session.find(1); if (s) { s->setFontNo(n_font); s->setSchemaNo(ColorSchema::find(s_schema)->numb); } else { fprintf(stderr,"session 1 not found\n"); } // oops // Default values for startup, changed by "save options". Not used by SM. defaultSize.setWidth ( config->readNumEntry("defaultwidth", 0) ); defaultSize.setHeight( config->readNumEntry("defaultheight", 0) ); } /* --| *Event |------------------------------------------------------------ */ void TEDemo::moveEvent (QMoveEvent *) { // Get another area of the background if ((useTransparency)&&(rootxpm)) rootxpm->setBackgroundPixmap(te); } void TEDemo::teChangedSize(int, int) { // Get another area of the background if ((useTransparency)&&(rootxpm)) rootxpm->setBackgroundPixmap(te); } void TEDemo::desktopChange(int d) { if ((useTransparency)&&(d==KWM::desktop(winId()))&&(d!=rootxpm->desktopNum()+1)) { // The user has changed desktop, it probably has another background, // so we have to re-read it // TODO : This should be optimized for oneDesktopMode (Antonio) ColorSchema *s=ColorSchema::find(curr_schema); if (rootxpm) delete rootxpm; rootxpm=new RootPixmap; rootxpm->prepareBackground(s->tr_r,s->tr_g,s->tr_b); rootxpm->setBackgroundPixmap(te); return; }; } /* ------------------------------------------------------------------------- */ /* */ /* */ /* ------------------------------------------------------------------------- */ void TEDemo::pixmap_menu_activated(int item) { if (useTransparency) { // If we want a transparent window, let's get it. ColorSchema *s=ColorSchema::find(curr_schema); if (rootxpm) delete rootxpm; rootxpm=new RootPixmap; // This is a new schema, so we should prepare the background // and (perhaps) tint it rootxpm->prepareBackground(s->tr_r,s->tr_g,s->tr_b); // Now, assign an area of the background to the te widget's background pixmap // but we'll let RootPixmap do the dirty work of guessing which part and // copy it rootxpm->setBackgroundPixmap(te); return; }; if (item <= 1) pmPath = ""; QPixmap pm(pmPath.data()); if (pm.isNull()) { pmPath = ""; item = 1; } // FIXME: respect scrollbar (instead of te->size) n_render = item; switch (item) { case 1: // none case 2: // tile te->setBackgroundPixmap(pm); break; case 3: // center { QPixmap bgPixmap; bgPixmap.resize(te->size()); bgPixmap.fill(te->getDefaultBackColor()); bitBlt( &bgPixmap, ( te->size().width() - pm.width() ) / 2, ( te->size().height() - pm.height() ) / 2, &pm, 0, 0, pm.width(), pm.height() ); te->setBackgroundPixmap(bgPixmap); } break; case 4: // full { float sx = (float)te->size().width() / pm.width(); float sy = (float)te->size().height() / pm.height(); QWMatrix matrix; matrix.scale( sx, sy ); te->setBackgroundPixmap(pm.xForm( matrix )); } break; default: // oops n_render = 1; } } void TEDemo::scrollbar_menu_activated(int item) { m_scrollbar->setItemChecked(n_scroll,FALSE); m_scrollbar->setItemChecked(item, TRUE); n_scroll = item; te->setScrollbarLocation(item); } void TEDemo::font_menu_activated(int item) { assert(se); se->setFontNo(item); activateSession((int)session2no.find(se)); // for attribute change // setFont(item) is probably enough } void TEDemo::schema_menu_activated(int item) { assert(se); //FIXME: save schema name se->setSchemaNo(item); activateSession((int)session2no.find(se)); // for attribute change // setSchema(item) is probably enough } void TEDemo::setFont(int fontno) { QFont f( fonts[fontno] ); f.setRawMode( TRUE ); if ( !f.exactMatch() ) { QString msg = i18n("Font `%1' not found.\nCheck README.linux.console for help.").arg(fonts[fontno]); QMessageBox::warning(this, i18n("Error - Konsole"), msg, i18n("&Ok")); } else { te->setVTFont(f); } m_font->setItemChecked(n_font,FALSE); m_font->setItemChecked(fontno, TRUE); n_font = fontno; } void TEDemo::setMenuVisible(bool visible) { b_menuvis = visible; m_options->setItemChecked(1,b_menuvis); if (b_menuvis) menubar->show(); else menubar->hide(); updateRects(); } void TEDemo::setFrameVisible(bool visible) { b_framevis = visible; m_options->setItemChecked(2,b_framevis); te->setFrameStyle( b_framevis ? QFrame::WinPanel | QFrame::Sunken : QFrame::NoFrame ); } void TEDemo::setBsHack(bool bshack) { b_bshack = bshack; m_options->setItemChecked(4,b_bshack); //FIXME: solve typing issue below if (se) if (b_bshack) ((VT102Emulation*)se->getEmulation())->setMode(MODE_BsHack); else ((VT102Emulation*)se->getEmulation())->resetMode(MODE_BsHack); } void TEDemo::opt_menu_activated(int item) { switch( item ) { case 1: setMenuVisible(!b_menuvis); if (!b_menuvis) { setCaption("Use the right mouse button to bring back the menu"); QTimer::singleShot(5000,this,SLOT(setHeader())); } break; case 2: setFrameVisible(!b_framevis); break; case 4: setBsHack(!b_bshack); break; case 8: saveProperties(kapp->getConfig()); break; } } // --| color selection |------------------------------------------------------- void TEDemo::changeColumns(int columns) { setColLin(columns,24); // VT100, FIXME: keep lines? te->update(); } void TEDemo::size_menu_activated(int item) { switch (item) { case 0: setColLin(40,15); break; case 1: setColLin(80,24); break; case 2: setColLin(80,25); break; case 3: setColLin(80,40); break; case 4: setColLin(80,52); break; } } void TEDemo::notifySize(int lines, int columns) { // printf("notifySize(%d,%d)\n",lines,columns); /* if (lines != lincol.height() || columns != lincol.width()) { char buf[100]; sprintf(buf,i18n("(%d columns x %d lines)"),columns,lines); setCaption(buf); QTimer::singleShot(2000,this,SLOT(setHeader())); } */ m_size->setItemChecked(0,columns==40&&lines==15); m_size->setItemChecked(1,columns==80&&lines==24); m_size->setItemChecked(2,columns==80&&lines==25); m_size->setItemChecked(3,columns==80&&lines==40); m_size->setItemChecked(4,columns==80&&lines==52); if (n_render >= 3) pixmap_menu_activated(n_render); } void TEDemo::setHeader() { setCaption(title); } void TEDemo::changeTitle(int, const char*s) { title = s; setHeader(); } // --| help |------------------------------------------------------------------ void TEDemo::about() //FIXME: make this a little nicer { QString title = i18n("About %1").arg(PACKAGE); QString msg = i18n( "%1 version %2 - an X terminal\n" "\n" "Copyright (c) 1998 by Lars Doelle \n" "\n" "This program is free software under the\n" "terms of the Artistic License and comes\n" "WITHOUT ANY WARRANTY.\n" "See `LICENSE.readmeŽ for details.").arg(PACKAGE).arg(VERSION); QMessageBox::information( 0, title, msg, i18n("&Ok") ); } void TEDemo::help() { kapp->invokeHTMLHelp(PACKAGE "/konsole.html",""); } void TEDemo::tecRef() { kapp->invokeHTMLHelp(PACKAGE "/techref.html",""); } /* --| sessions |------------------------------------------------------------ */ //FIXME: activating sessions creates a lot flicker in the moment. // it comes from setting the attributes of a session individually. // ONE setImage call should actually be enough to match all cases. // These can be quite different: // - The screen size might have changed while the session was // detached. A propagation of the resize should in this case // make the drawEvent. // - font, background image and color palette should be set in one go. void TEDemo::activateSession(int sn) { TESession* s = no2session.find(sn); if (se) { se->setConnect(FALSE); int no = (int)session2no.find(se); m_sessions->setItemChecked(no,FALSE); } se = s; if (!s) { fprintf(stderr,"session not found\n"); return; } // oops m_sessions->setItemChecked(sn,TRUE); setSchema(s->schemaNo()); //FIXME: creates flicker? Do only if differs //Set Font. Now setConnect should do the appropriate action. //if the size has changed, a resize event (noticable to the application) //should happen. Else, we could even start the application s->setConnect(TRUE); // does a bulkShow (setImage) setFont(s->fontNo()); //FIXME: creates flicker? //FIXME: check here if we're still alife. // if not, quit, otherwise, // start propagating quit. title = s->Title(); // take title from current session setHeader(); } void TEDemo::runSession(TESession* s) { int session_no = (int)session2no.find(s); activateSession(session_no); // give some time to get through the // resize events before starting up. QTimer::singleShot(100,s,SLOT(run())); } void TEDemo::addSession(TESession* s) { session_no += 1; no2session.insert(session_no,s); session2no.insert(s,(void*)session_no); m_sessions->insertItem(s->Title(), session_no); } void TEDemo::newSession(int i) { const char* shell = getenv("SHELL"); if (shell == NULL || *shell == '\0') shell = "/bin/sh"; KSimpleConfig* co = no2command.find(i); if (!co) return; // oops assert( se ); //FIXME: careful here. QString cmd = co->readEntry("Exec"); // not null QString nam = co->readEntry("Name"); // not null QString emu = co->readEntry("Term"); QString sch = co->readEntry("Schema"); QString txt = co->readEntry("Comment"); // not null int fno = QMIN(co->readUnsignedNumEntry("Font",se->fontNo()),7); ColorSchema* schema = sch.isEmpty() ? (ColorSchema*)NULL : ColorSchema::find(sch); //FIXME: schema names here are absolut. Wrt. loadAllSchemas, // relative pathes should be allowed, too. int schmno = schema?schema->numb:se->schemaNo(); if (emu.isEmpty()) emu = se->emuName(); QStrList args; args.append(shell); args.append("-c"); args.append(cmd); TESession* s = new TESession(this,te,args,emu.data(),0); s->setFontNo(fno); s->setSchemaNo(schmno); s->setTitle(txt.data()); addSession(s); runSession(s); // activate and run } //FIXME: If a child dies during session swap, // this routine might be called before // session swap is completed. void TEDemo::doneSession(TESession* s, int ) { //printf("%s(%d): Exited:%d ExitStatus:%d\n",__FILE__,__LINE__,WIFEXITED(status),WEXITSTATUS(status)); #if 0 // die silently if (!WIFEXITED((status)) || WEXITSTATUS((status))) { //FIXME: "Title" is not a precise locator for the message. // The command would be better. QString str = i18n("`%1' terminated abnormally.").arg(s->Title()); if (WIFEXITED((status))) {char rcs[100]; sprintf(rcs,"%d.\n",WEXITSTATUS((status))); str = str + i18n("\nReturn code = ") + rcs; } QMessageBox::warning(this, i18n("Error"), str, i18n("&OK")); } #endif int no = (int)session2no.find(s); if (!no) return; // oops no2session.remove(no); session2no.remove(s); m_sessions->removeItem(no); s->setConnect(FALSE); // This slot (doneSession) is activated from the Shell when receiving a // SIGCHLD. A lot is done during the signal handler, apparently deleting // the Shell additionally, is sometimes too much, causing something // to get messed up in rare cases. The following causes delete not to // be called from within the signal handler. QTimer::singleShot(100,s,SLOT(terminate())); if (s == se) { // pick a new session se = NULL; QIntDictIterator it( no2session ); if ( it.current() ) activateSession(it.currentKey()); else kapp->quit(); } } // --| Session support |------------------------------------------------------- void TEDemo::addSessionCommand(const char* path) { KSimpleConfig* co = new KSimpleConfig(path,TRUE); co->setDesktopGroup(); QString typ = co->readEntry("Type"); QString txt = co->readEntry("Comment"); QString cmd = co->readEntry("Exec"); QString nam = co->readEntry("Name"); if (typ.isEmpty() || txt.isEmpty() || cmd.isEmpty() || nam.isEmpty() || strcmp(typ.data(),"KonsoleApplication")) { delete co; return; // ignore } m_file->insertItem(txt, ++cmd_serial); no2command.insert(cmd_serial,co); } void TEDemo::loadSessionCommands() { QStringList lst = KGlobal::dirs()->findAllResources("appdata", "*.desktop", false, true); for(QStringList::Iterator it = lst.begin(); it != lst.end(); ++it ) addSessionCommand(*it); } // --| Schema support |------------------------------------------------------- void TEDemo::setSchema(int numb) { ColorSchema* s = ColorSchema::find(numb); if (s) setSchema(s); } void TEDemo::setSchema(const char* path) { ColorSchema* s = ColorSchema::find(path); if (s) setSchema(s); } void TEDemo::setSchema(const ColorSchema* s) { if (!s) return; m_schema->setItemChecked(curr_schema,FALSE); m_schema->setItemChecked(s->numb,TRUE); s_schema = s->path; curr_schema = s->numb; pmPath = s->imagepath; te->setColorTable(s->table); //FIXME: set twice here to work around a bug useTransparency=s->usetransparency; if (useTransparency) { // we want to be notified when the user changes desktop, so let's connect to KWM while (!KWM::isKWMInitialized()) sleep(1); if (!KWM::isKWMModule(winId())) ((KWMModuleApplication *)kapp)->connectToKWM(); } pixmap_menu_activated(s->alignment); te->setColorTable(s->table); if (se) se->setSchemaNo(s->numb); } /* --| main |---------------------------------------------------------------- */ static void usage() { fprintf (stderr, "usage: %s [option ...]\n" "%s version %s, an X terminal for KDE.\n" "\n" " -e Command Parameter ... Execute command instead of shell\n" " -name .................. Set Window Class\n" " -h ..................... This text\n" " -ls .................... Start login shell\n" " -nowelcome ............. Suppress greeting\n" " -sl ........... Save number lines in scroll-back buffer\n" " -vt_sz CCxLL ........... terminal size in columns x lines \n" "\n" "Other options due to man:X(1x), Qt and KDE, among them:\n" "\n" " -caption 'Text'......... Set title\n" " -display ..... Set the X-Display\n" ,PACKAGE,PACKAGE,VERSION ); } extern int maxHistLines; int main(int argc, char* argv[]) { setuid(getuid()); setgid(getgid()); // drop privileges kimgioRegister(); // add io for additional image formats // deal with shell/command //////////////////////////// int login_shell=0; int welcome=1; const char* shell = getenv("SHELL"); const char* wname = PACKAGE; if (shell == NULL || *shell == '\0') shell = "/bin/sh"; QString sz = ""; QStrList eargs; eargs.append(shell); setlocale( LC_ALL, "" ); KWMModuleApplication a(argc, argv, PACKAGE); for (int i = 1; i < argc; i++) { if (!strcmp(argv[i],"-e") && i+1 < argc) // handle command { if (login_shell) fprintf(stderr,"-e excludes -ls.\n"); login_shell = 0; // does not make sense here. eargs.clear(); int j; for (j = 0; j+i+1 < argc; j++) eargs.append( argv[i+j+1] ); break; } if (!strcmp(argv[i],"-vt_sz") && i+1 < argc) sz = argv[++i]; if (!strcmp(argv[i],"-sl") && i+1 < argc) { QString a(argv[++i]); maxHistLines = a.toInt(); } if (!strcmp(argv[i],"-name") && i+1 < argc) wname = argv[++i]; if (!strcmp(argv[i],"-ls") ) login_shell=1; if (!strcmp(argv[i],"-nowelcome")) welcome=0; if (!strcmp(argv[i],"-h")) { usage(); exit(0); } if (!strcmp(argv[i],"-help")) { usage(); exit(0); } if (!strcmp(argv[i],"--help")) { usage(); exit(0); } //FIXME: more: font, menu, scrollbar, schema, session ... } // /////////////////////////////////////////////// putenv("COLORTERM="); //FIXME: for mc, which cannot detect color terminals int c = 0, l = 0; if ( (strcmp("", sz) != 0) ) { char *ls = strchr( sz, 'x' ); if ( ls != NULL ) { *ls='\0'; ls++; c=atoi(sz); l=atoi(ls); } else { fprintf(stderr, "expected -vt_sz <#columns>x<#lines> ie. 80x40\n" ); } } if (a.isRestored()) { KConfig * sessionconfig = a.getSessionConfig(); sessionconfig->setGroup("options"); sessionconfig->readListEntry("konsolearguments", eargs); wname = sessionconfig->readEntry("class",wname).data(); RESTORE( TEDemo(wname,eargs,login_shell) ) } else { TEDemo* m = new TEDemo(wname,eargs,login_shell); m->setColLin(c,l); // will use default height and width if called with (0,0) if (welcome) { m->setCaption(i18n("Welcome to the console")); QTimer::singleShot(5000,m,SLOT(setHeader())); } m->show(); } return a.exec(); } #include "main.moc"