/* TUIpeer works in conjunction with an implementation of java.awt.Toolkit to provide a Text User Interface for programs using the Java AWT. The Toolkit class dispatches local and remote events to the appropriate components. Copyright (C) 1997-2000 Stuart D. Gathman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* $Log: toolkit.cc,v $ /* Revision 1.2 2000/12/18 01:58:57 stuart /* Removed dependencies on libg++. /* Changed all references to String to string. /* Changed libg++ String idioms to string idioms. /* Copied Obstack from libg++ and hacked it to throw an exception on error. /* Hacked Set.cc to throw an exception on error. /* Added Str.cc to relace the split function from libg++. /* /* Revision 1.1.1.1 2000/12/16 20:45:13 stuart /* Released TUIPeer sources /* * Revision 1.2 2000/12/14 20:53:56 stuart * Changes for Linux * // Revision 1.1 1997/09/18 23:03:16 stuart // Initial revision // */ #pragma implementation #include #include #include #include #include #include #include #include #include "toolkit.h" #include "wincomp.h" #include Toolkit::Toolkit(int sock): SelectPoll(&SelectRead) { trace = false; localtabs = false; scalex = 1; scaley = 1; fd = sock; dumpargs = 0; backgrnd = new Background; ContainerComponent *factory = new ContainerComponent; objs.add(factory); factory->compID = 0; factory->toolkit = this; f = 0; } void Toolkit::init(int sx,int sy) { scalex = sx; scaley = sy; if (fd >= 0) { callMethod(0,RemotePeer::SETSCALE,scalex,scaley); callMethod(0,RemotePeer::SCREENSIZE, Window::screen.width() * scalex,Window::screen.height() * scaley); arm(fd); setfocus(this); f = fdopen(fd,"r"); } } Toolkit::~Toolkit() { close(); for (int i = 0; i < objs.size(); ++i) delete objs[i]; delete backgrnd; PSend(); // sometimes we don't manage to destroy all windows fprintf(stderr,"toolkit shutdown\n"); } void Toolkit::close() { if (f != 0) fclose((FILE *)f); f = 0; fd = -1; } void Toolkit::key(int k) { switch (k) { case KEY_F(1): case KEY_EXIT: case KEY_CLOSE: setfocus(0); return; case KEY_SELECT: { Dialog *w = pickList(); if (w) setfocus(w); return; } case KEY_NEXT: nextFrame(); return; case KEY_PREVIOUS: prevFrame(); return; } Controller::key(k); } void Toolkit::nextFrame() { if (allFrames.size() < 2) return; addFrame(allFrames[0]); } void Toolkit::prevFrame() { int n = allFrames.size(); if (n < 2) return; addFrame(allFrames[n-2]); } void Toolkit::getfocus() { int n = allFrames.size(); if (n > 0) setfocus(allFrames[n-1]); } Dialog *Toolkit::pickList() { int n = allFrames.size(); if (n == 0) return 0; StringArray list; for (int j = 0; j < n; ++j) { Dialog *w = allFrames[j]; if (w->isVisible()) list.put(w->getTitle()); } /* list.sort(); */ bmsListBox listbox("Task List",list); Rect &r = Window::gettop()->loc; listbox.setpos(Point(r.r1,r.c1)); int ky; do { setfocus(&listbox); ky = listbox.run(); } while (ky < 0); if (ky == KEY_F(1)) return 0; int i = listbox.get(); return (i < n) ? allFrames[i] : 0; } void Toolkit::addComponent(Component *obj,int id) { obj->toolkit = this; obj->compID = id; if (id == objs.size()) objs.add(obj); else objs[id] = obj; } void Toolkit::delComponent(int id) { delete removeComponentAt(id); if (id == 0) { close(); setfocus(0); // JavaVM connection is dead //PSend(); // shortcut shutdown //exit(0); } } Component *Toolkit::removeComponentAt(int id) { int n = objs.size(); if (id < 0 || id >= n) return 0; Component *obj = objs[id]; if (obj) { objs[id] = 0; for (id = n - 1; id >= 0; --id) if (objs[id] != 0) break; if (++id < n) objs.del(id,n - id); } return obj; } Component *Toolkit::componentAt(int id) { if (id >= objs.size() || id < 0) return 0; return objs[id]; } struct MethodDesc { const char *name; int id; const char *args; }; void Toolkit::logarg(int v) { fprintf(stderr,"%c%d",dumpargs,(short)v); if (argcnt && !--argcnt) fputc('\n',stderr); //fflush(stderr); } void Toolkit::logarg(const char *s) { fprintf(stderr,"%c%s",dumpargs,s); if (argcnt && !--argcnt) fputc('\n',stderr); //fflush(stderr); } #define METHOD(n,i,a) { #n,i,a }, static MethodDesc methodTable[] = { #include "method.def" { 0,-1,"" } }; #undef METHOD static int methodName(int v) { int i; for (i = 0; methodTable[i].id >= 0; ++i) if (methodTable[i].id == v) return i; static char buf[32]; sprintf(buf,"OP[%d]",v); methodTable[i].name = buf; return i; } void Toolkit::handler() { do { int objid = readShort(); int cmd = readShort(); if (objid < 0 || objid >= objs.size()) { if (trace) fprintf(stderr,"Invalid message: %02X %02X\n",objid,cmd); return; } if (cmd == Component::DISPOSE) { if (trace) fprintf(stderr,"CMD: %d, DISPOSE\n",objid); delComponent(objid); return; } Component *comp = objs[objid]; if (trace) { int i = methodName(cmd); argcnt = strlen(methodTable[i].args); if (methodTable[i].args[0] == 'R') argcnt = 0; fprintf(stderr,"CMD: %d, %s",(short)objid,methodTable[i].name); if (argcnt == 0) fputc('\n',stderr); else dumpargs = ','; } //fflush(stderr); comp->remoteMethod(cmd); dumpargs = 0; } while (avail()); } void Toolkit::writeShort(int val) { char buf[2]; buf[0] = val >> 8; buf[1] = val & 255; if (this == 0) return; write(fd,buf,2); } void Toolkit::readFully(char *buf,int size) { while (size > 0) { #if 1 int c = getc((FILE *)f); if (c == EOF) { perror("readSocket"); disarm(); break; } *buf++ = c; --size; #else int n = read(fd,buf,size); if (n <= 0) { perror("readSocket"); disarm(); break; } buf += n; size -= n; #endif } } int Toolkit::readShort() { char buf[2]; buf[0] = 0; buf[1] = 0; readFully(buf,2); int v = (buf[0] << 8) + (buf[1] & 255); if (dumpargs) logarg(v); return v; } string Toolkit::readUTF() { char sav = dumpargs; dumpargs = 0; unsigned len = readUshort(); dumpargs = sav; char *buf = (char *)alloca(len + 1); readFully(buf,len); buf[len] = 0; if (dumpargs) logarg(buf); // All chars must be ASCII for now... return string(buf,len); } void Toolkit::callMethod(int objid,int cmd,const string &s) { callMethod(objid,cmd); writeUTF(s); } void Toolkit::callMethod(int id,int cmd,const char *buf,int len) { callMethod(id,cmd,len); write(fd,buf,len); } void Toolkit::callMethod(int objid,int cmd,int x,int y) { if (trace) fprintf(stderr,"SND: %d,%s,%d,%d\n", objid,methodTable[methodName(cmd)].name,x,y); writeShort(objid); writeShort(cmd); writeShort(x); writeShort(y); } void Toolkit::callMethod(int objid,int cmd,int x,int y,int w,int h) { if (trace) fprintf(stderr,"SND: %d,%s,%d,%d,%d,%d\n", objid,methodTable[methodName(cmd)].name,x,y,w,h); writeShort(objid); writeShort(cmd); writeShort(x); writeShort(y); writeShort(w); writeShort(h); } void Toolkit::callMethod(int objid,int cmd,int x) { if (trace) fprintf(stderr,"SND: %d,%s,%d\n",objid,methodTable[methodName(cmd)].name,x); writeShort(objid); writeShort(cmd); writeShort(x); } void Toolkit::callMethod(int objid,int cmd) { if (trace) fprintf(stderr,"SND: %d,%s\n",objid,methodTable[methodName(cmd)].name); writeShort(objid); writeShort(cmd); } void Toolkit::writeUTF(const string &s) { int len = s.length(); writeShort(len); write(fd,s.c_str(),len); } void Toolkit::addFrame(Dialog *w) { int i = findFrame(w); if (i >= 0) allFrames.del(i); allFrames.add(w); setfocus(w); } int Toolkit::findFrame(Component *obj) { int n = allFrames.size(); if (n > 0) { Dialog **a = &allFrames[0]; for (int i = 0; i < n; ++i) if (a[i] == obj) return i; } return -1; } void Toolkit::removeFrame(Component *obj) { int i = findFrame(obj); if (i >= 0) { allFrames.del(i); int n = allFrames.size(); if (n > 0) setfocus(allFrames[n-1]); else obj->setfocus(0); } } int Toolkit::avail() { if (!f) return -1; int n = favail((FILE *)f); #ifdef FIONREAD if (n == 0) ioctl(fd,FIONREAD,&n); #endif return n; } static int getkey(void); int Toolkit::run() { int ky = 0; while (isActive() && f != 0) { if (!avail()) Ksync(); ky = getkey(); if (ky == -1) continue; if (dokey(ky)) break; } return ky; } static int getkey(void) { for (;;) { PSsync(); fskey = Kget(); switch (fskey) { case KEY_PRINT: { int euid = geteuid(); int egid = getegid(); setuid(getuid()); setgid(getgid()); PSprtscr("scrndump"); setuid(euid); setgid(egid); continue; } case KEY_REFRESH: PSrefresh(); PSsync(); continue; } return fskey; } } int Toolkit::runProg(string cmd) { Program p; p.setfd(0,dup(0)); p.setfd(1,dup(1)); p.setfd(2,dup(1)); dropscrn(); p.runAs(getuid(),getgid()).run(cmd.c_str()); int rc = p.wait(); restscrn(); return rc; }