/* * Implementation of RSLBrowser. */ #include "browser.h" #include #include class StringBrowser; RSLBrowser::RSLBrowser(TransInterface* ti, World* world, int argc, char** argv, exception* exitExc) { this->ti = ti; this->world = world; Insert(Init(argc, argv, exitExc)); SetName("RSL Text Browser/Editor"); SetIconName("Text Browser"); Init2(); } Interactor* RSLBrowser::Init(int argc, char** argv, exception* exitExc) { /* * Build all the UI components and stick them in the right places. The * interactor that Init returns is inserted as the RSLBrowser's sole tray * element. */ /* * Do the init that ANSI C++ forbids where it should be allowed (i.e., in * the .h file). */ editMode = false; transientMenus = false; autoGraphics = false; numBrRows = 15; numBrCols = 40; numEdRows = 20; numEdCols = 80; ednum = 1; /* * Process the command line files and switches. */ ProcessCommandLineArgs(argc, argv); /* * Make the intial menubar containing File, Edit, and Modules menus. */ menuBar = new RSLMenuBar(this, ti, exitExc); /* * Make the current entity and file str editors. */ curEntity = new EntityStrEd(this); curFile = new FilenameStrEd(this); /* * The str eds come up filled with blanks, which is rather unattractive, * and a general pain to boot. */ curEntity->Message(""); curFile->Message(""); /* * Make the obj and op str browsers. */ entBrowsers = new EntityStrBrowserPair(this, numBrRows, numBrCols); /* * Install the names in the Modules menu and entity browsers. Note that * this needs to be done before layout, since, among other reasons, the str * browsers will get horz scrollers only if there is a name wider than the * standard width. */ InstallNames(); /* * Create the initial text editor list, containing one empty editor. */ codeEds = new EntityTextEdList(); /* * NOT anymore for the empty fixed editor * EntityTextEd* ed = new EntityTextEd(numEdRows, numEdCols, not editMode, codeEds, this); codeEds->SetFixedEd(ed); * */ /* * Create the initially unmapped graphics editor. */ graphicEd = new EntityGraphicEd(); /* * Create a undef entity dialog for possible later use. */ undefEntity = new UndefEntityDialog(new ButtonState(1)); /* * Put the pieces together in a nice box and return it. */ return Layout(); } void RSLBrowser::ProcessCommandLineArgs(int argc, char** argv) { /* * Copy the command-line args into the local member. When new files are * opened, the names are appended to argv (see AddFile()). */ tfilelist = new StrList(); gfilelist = new StrList(); this->argc = 1; this->tiargc = 1; int i; for (i=1; iFind(gfn)) and fopen(gfn, "r")) { gfilelist->Put(new StrListElem(gfn, null)); } } } #endif } void RSLBrowser::ProcessCommandLineSwitch(const char* arg) { /* * Do what the command line switch says to do and/or send it to the translator * on the next rescan. */ if (IsTransSwitch(arg)) { tiargv[tiargc++] = newstr(arg); return; } } bool RSLBrowser::IsTransSwitch(const char* arg) { return ( (arg[1] == 'm') or ((arg[1] == 'o') and (arg[2] == 'o')) or (arg[1] == 's') or (arg[1] == 't') ); } Box* RSLBrowser::Layout() { /* * Stick the pieces together in a nice set of boxes. */ VBox* outer = new VBox(); HBox* innerOuter = new HBox(); VBox* innerInnerOuter = new VBox(); outer->Insert(menuBar); outer->Insert(new VGlue(round(0.2*inch))); innerOuter->Insert(new HGlue(round(0.2*inch))); innerInnerOuter->Insert(LayoutStrEds()); innerInnerOuter->Insert(new VGlue(round(0.25*inch))); innerInnerOuter->Insert(LayoutStrBrowsers()); innerInnerOuter->Insert(new VGlue(round(0.25*inch))); innerOuter->Insert(innerInnerOuter); innerOuter->Insert(new HGlue(round(0.2*inch))); outer->Insert(innerOuter); //outer->Insert(new VGlue(round(0.2*inch))); LayoutTextEds(); return outer; } Interactor* RSLBrowser::LayoutStrEds(){ /* * Layout the selected entity and file str eds. */ VBox* entBox = new VBox(); VBox* fileBox = new VBox(); HBox* edsBox = new HBox(); entBox->Insert(new PaintLabel("Selected Entity:", "times", "bold", "r", "14")); entBox->Insert(new Frame(curEntity)); fileBox->Insert(new PaintLabel("File:", "times", "bold", "r", "14")); fileBox->Insert(new Frame(curFile)); edsBox->Insert(entBox); edsBox->Insert(new HGlue(round(0.7 * inch))); edsBox->Insert(fileBox); return edsBox; } Interactor* RSLBrowser::LayoutStrBrowsers(){ return entBrowsers->Layout(); } void RSLBrowser::LayoutTextEds(){ int i; for (i = 1; i < argc; i++) { EntityTextEd* ed = new EntityTextEd(numEdRows, numEdCols, not editMode, codeEds, argv[i], this); codeEds->Add(ed); codeEds->Open(argv[i]); } codeEds->MakeCur((EntityTextEd*) null); menuBar->UpdateFileMenuList(tfilelist); fileSubmenuListNeedsUpdating = false; } void RSLBrowser::LayoutScreen() { /* * Stick this into the upper left corner of the screen and pile the text * eds up neatly below. */ world->InsertApplication(this, 10, 550); EntityTextEdListElem* el; edx = 40; edy = 260; while (el = codeEds->Enum()) { EntityTextEd* ed = el->GetData(); world->InsertApplication(ed, edx, edy); IncrEdPos(); } } RSLBrowser* RSLBrowser::Init2() { menubarNeedsUpdating = false; fileSubmenuListNeedsUpdating = false; return this; } RSLBrowser* RSLBrowser::UpdateCurEntity(EntityStruct* es) { /* * Update the state of the browser to make the given entity current. * See the .h file comment for the details. */ if (not es) { curEntity->Message(""); menuBar->UpdateModuleMenuBar(es); entBrowsers->Unselect(); return this; } if (es->GetSym()) { this->es = es; UpdateEntityName(es); UpdateFileName(es); UpdateStrBrowsers(es); UpdateText(es); menubarNeedsUpdating = true; /* See comment in .h file for Run() */ /* Change(); -- does nothing but annoy */ } else { char buf[200]; sprintf(buf, "Entity %s is undefined in the current module scope", es->GetName()); undefEntity->Popup(buf, world); } return this; } RSLBrowser* RSLBrowser::UpdateCurEntity(const char* ename) { /* * Version of UpdateCurEntity that takes a qualified disambiguated string name * instead of an EnityStruct. This version is called from inside the * current entity str ed (when return is hit after some typing * (presumably)). A quick lookup in the browser symtab finds the symbol * by name, if it exists, and then calls UpdateCurEntity(EntityStruct*). * * The form of the string is exactly as it appears in the selected entity * window: "object"|"operation" [ "(in module " " )" ] * * Note that if the lookup fails, only the bell is beeped. A written error * message is deemed inappropriate since this is expected to be an untypical * route for the user to follow. If a completion editor is ever implemented, * things might change in this regard. */ EntityStruct* es; if (es = entBrowsers->Lookup(ename)) UpdateCurEntity(es); else world->RingBell(100); return this; } RSLBrowser* RSLBrowser::GotoPicture(const char* ename) { /* * Given a picture name, tell the graphic browser to make it current. */ return this; } RSLBrowser* RSLBrowser::EnterEditMode() { /* * Enter edit mode. Per the users man, the browsing menus are shut down * and editing is enabled in the text and graphics editors. */ editMode = true; codeEds->ReadonlyOff(); DisableBrowsing(); return this; } RSLBrowser* RSLBrowser::ExitEditMode() { /* * Reenable browsing and disable editing, after rechecking everything. */ if (Rescan()) { editMode = false; codeEds->ReadonlyOn(); } return this; } RSLBrowser* RSLBrowser::ToggleEditBrowseMode() { if (editMode) return ExitEditMode(); else return EnterEditMode(); } RSLBrowser* RSLBrowser::EnterTransientMenus() { transientMenus = true; menubarNeedsUpdating = true; return this; } RSLBrowser* RSLBrowser::ExitTransientMenus() { transientMenus = false; menubarNeedsUpdating = true; return this; } RSLBrowser* RSLBrowser::ToggleTransientMenusMode() { if (transientMenus) return ExitTransientMenus(); else return EnterTransientMenus(); } RSLBrowser* RSLBrowser::EnterAutoGraphicsMode() { return this; } RSLBrowser* RSLBrowser::ExitAutoGraphicsMode() { return this; } RSLBrowser* RSLBrowser::ToggleAutoGraphicsMode() { if (autoGraphics) return ExitAutoGraphicsMode(); else return EnterAutoGraphicsMode(); } RSLBrowser* RSLBrowser::SetTransFlags(StrList* flags) { return this; } bool RSLBrowser::Rescan() { /* * Call the translator to retranslate the currently open files. The * translator is called with all of the currently open files, which * include those originally given in the argv command line plus those * subsequently opened by the user using Menus.File.Open. * * After translation, we rebuild the name lists in the Objects and * Operations browsers, and install the initial menubar. */ /* * Write all the open files. */ SaveAll(); /* * Do the translation. */ int result = ti->ReTranslate(argc, argv); /* * Check the result and enable or disable browsing accordingly. */ if (result >= 0) { InstallNames(); rescanfailed = false; /* Others, such as menubar, need to know this*/ return true; } else { ErrorDialog("Translation errors; see output on stderr in original invocation window. Browsing is disabled"); DisableBrowsing(); rescanfailed = false; /* Others, such as menubar, need to know this*/ return false; } } RSLBrowser* RSLBrowser::Open(const char* filename) { /* * Call the transaltor to (incrementally) translate the given file. Add * the file name to the currently open files if it translates OK, then recheck * all of the files. */ /* * Dialog if file already open. */ EntityTextEdListElem* ede; bool replacing = false; bool newing = false; if (ede = codeEds->Find(filename)) { if (not ChooseDialog("File already open, replace?")) return this; replacing = true; } /* * Dialog if file not found. */ if (not OpenNew(filename)) return this; newing = true; /* * Raise existing editor or create a new one, as appropriate. */ if (ede) { EntityTextEd* ed = ede->GetData(); codeEds->MakeCur(ed); codeEds->Open(filename); world->Raise(ed); } else { NewEditor(filename); } /* * Do the translation. */ if (newing or (ti->TranslateOne(filename))) { if (not replacing) { AddArg(filename); } Rescan(); } else ErrorDialog("File translation errors; see output on stderr in original invocation window. File not opened."); return this; } RSLBrowser* RSLBrowser::OpenFromTypeIn(const char* filename) { /* * Open a filename that was typed into the File stred. If it's already * open, we just expose it, if it's not, we dialog as in Open. */ /* * Complain and exit if empty filename (happens if user just hits return in * empty filename str ed). */ if (streq(filename, "")) { ErrorDialog("Empty file name."); return this; } /* * Raise its ed window if file already open. */ EntityTextEdListElem* ede; bool newing = false; if (ede = codeEds->Find(filename)) { EntityTextEd* ed = ede->GetData(); codeEds->MakeCur(ed); world->Raise(ed); return this; } /* * Dialog if file not found. */ if (not OpenNew(filename)) return this; newing = true; /* * Create a new file editor. */ NewEditor(filename); /* * Do the translation. */ if (newing or (ti->TranslateOne(filename))) { AddArg(filename); Rescan(); } else ErrorDialog("File translation errors; see output on stderr in original invocation window. File not opened."); return this; } bool RSLBrowser::OpenNew(const char* filename) { if (not fopen(filename, "r")) { if (fopen(filename, "w")) { if (not ChooseDialog( "File not found, open anyway as a new file?")) { return false; } else if (not ChooseDialog( "File not found and not writeable, open anyway?")) { return false; } } } return true; } RSLBrowser* RSLBrowser::Save() { return Save(codeEds->CurEd()); } RSLBrowser* RSLBrowser::Save(EntityTextEd* ed) { if (ed->Save()) return this; const char* filename = ed->GetFilename(); char* buf = new char[ strlen("File is not writeable; use 'Save As' to change name.") + strlen(filename) + 1]; sprintf(buf, "File %s is not writeable; use 'Save As' to change name.", filename); ErrorDialog(buf); return this; } static char* fn; RSLBrowser* RSLBrowser::SaveAs(const char* filename) { fn = newstr(filename); return SaveAs(codeEds->CurEd(), filename); } RSLBrowser* RSLBrowser::SaveAs(EntityTextEd* ed, const char* filename) { if (not ed) { ErrorDialog("No file currently active."); return this; } if (codeEds->Find(filename)) { ErrorDialog("That file is already open."); /* SaveAsLoop(ed); MAYBE LATER */ return this; } if (fopen(filename, "r")) { if (not ChooseDialog("File exists, write anyway?")) return this; } char* origname = newstr(ed->GetFilename()); if (ed->SaveAs(filename)) { DeleteArg(origname); AddArg(filename); // codeEds->ChangeName(origname, filename); deletedFile = origname; /* Redo after AddArg undoes */ //delete origname; /* * OK, guess why this resscan is necessary. Well it's a bit subtle. * The deal is that all of the browsable entities still hold the old * filename in there symbols. So, we need to retranslate the file so * that the Loc.file fields are updated to the name of the file we just * renamed to. It would be nice if we could just incrementally * retranslate this file, but we're not currently tooled to do this, so * we rescan the whole wad. Maybe LATER for the incremental stuff. */ Rescan(); return this; } const char* filename1 = ed->GetFilename(); char* buf = new char[ strlen("File is not writeable; choose another name.") + strlen(filename1) + 1]; sprintf(buf, "File %s is not writeable; choose another name.", filename1); ErrorDialog(buf); delete buf; return this; } RSLBrowser* RSLBrowser::SaveAll() { EntityTextEdListElem* el; while (el = codeEds->Enum()) { Save(el->GetData()); } return this; } /* * Dormant. */ void RSLBrowser::SaveAsLoop(EntityTextEd* ed) { if (not filedialog) filedialog = new FileDialog(this); const char* filename; while (true) { filename = filedialog->ChooseFile(filename); if (not filename) break; if (codeEds->Find(filename)) { ErrorDialog("File already open, choose another."); filename = null; continue; } if (SaveAs(filename)) break; ErrorDialog("File not writeable, choose another."); filename = null; } /* * FIX if we go undormant. */ if (filename) { DeleteArg(ed->GetFilename()); AddArg(filename); } } EntityTextEd* RSLBrowser::CurEd() { return codeEds->CurEd(); } RSLBrowser* RSLBrowser::Close(const char* filename) /* * Close the given file and remove the editor in which it resides. */ { EntityTextEd* ed = codeEds->DelNth(codeEds->FindPos(filename))->GetData(); if (codeEds->CurEd() == ed) { codeEds->MakeCur((EntityTextEd*) null); curFile->Message(""); UpdateCurEntity((EntityStruct*) null); } world->Remove(ed); delete ed; DeleteArg(filename); /* * Note that we must do a full rescan here, since we must remove all * entities from the str browsers that were in the just-deleted file. * Also, we may have deleted a file with exports that other modules * import, which invalidates the full translation and therefore the * browsing environment. */ Rescan(); return this; } RSLBrowser* RSLBrowser::Expose(const char* filename) /* * Expose the ed in which the given file resides. */ { EntityTextEd* ed = codeEds->Find(filename)->GetData(); world->Raise(ed); if (codeEds->CurEd() != ed) { codeEds->MakeCur(ed); UpdateCurEntity((EntityStruct*) null); } return this; } RSLBrowser* RSLBrowser::SearchForw(const char* searchstring) { /* * Call the texted to do the search in the current ed. */ /* * es == null only happens before any entity has been selected, which means * someone is searching immediately after startup, which means that the * search will happen by (accidental) default in the last file opened, * which doesnt make much sense, which means we'll just not do the search * at all, which is not really a big deal, and therefore this commment is * far longer than it is important. */ if (es) codeEds->SearchForw(searchstring); return this; } RSLBrowser* RSLBrowser::SearchBack(const char* searchstring) { /* * Ibid. */ if (es) codeEds->SearchBack(searchstring); return this; } RSLBrowser* RSLBrowser::GotoLine(int line) { /* * Goto the specified line in the current editor. */ codeEds->GotoLine(line); return this; } RSLBrowser* RSLBrowser::NewEditor(const char* filename) { /* * Create a new, detached, text ed window and make it current. Its * contents are intially empty (later we may implement the filename parm, which * would cause the intial contents to be the file so named. */ EntityTextEd* ed = new EntityTextEd(numEdRows, numEdCols, not editMode, codeEds, filename, this); /* char buf[50]; sprintf(buf, "Text Ed %i", ednum++); ed->SetIconName(buf); */ codeEds->Add(ed); world->InsertApplication(ed, edx, edy); IncrEdPos(); return this; } bool RSLBrowser::InEditMode() { /* * Return true if currenly in edit mode, false otherwise. Used by Exit, * among possibly others. */ return editMode; } bool RSLBrowser::InTransientMenusMode() { return transientMenus; } bool RSLBrowser::InAutoGraphicsMode() { return autoGraphics; } RSLBrowser* RSLBrowser::Edit(char* path) { /* * Open the given path in the current ed, if it's not already. */ return this; } void RSLBrowser::CheckExit() { } void RSLBrowser::Run() { /* * See .h file for full comment. The code here is from iv's Interactor::Run, * with check added for menubar updating. */ Event e; do { Read(e); e.target->Handle(e); if (MenubarNeedsUpdating()) { UpdateMenuBar(es); /* * Since the menuBar may have changed its config, we call Change on * ourself to redisplay. Recall that the RSLBrowser is itself a * monoscene, so the call here is to Monoscene::Change. * Change(menuBar); * NOT -- this really sucks; the menubar wont change without * twitching. Damn! */ } } while (e.target != nil); } bool RSLBrowser::ObjIsCur() { /* * Return true if the current entity is an object. */ if (not es) return false; return es->GetSym()->Class == C_Obj; } bool RSLBrowser::OpIsCur() { /* * Return true if the current entity is an operation. */ if (not es) return false; return es->GetSym()->Class == C_Op; } const char* RSLBrowser::EnumTFiles() { /* * Enumerate the open text files. */ StrListElem* sle = tfilelist->Enum(); if (sle) { return sle->GetData()->ConstConvert(); } else { return NULL; } } const char* RSLBrowser::EnumGFiles() { /* * Enumerate the open text files. */ StrListElem* sle = gfilelist->Enum(); if (sle) { return sle->GetData()->ConstConvert(); } else { return NULL; } } bool RSLBrowser::MenubarNeedsUpdating() { /* * Per lengthy comment at Run(), this lets outside event handlers (e.g., * EntityDtrBrowser::Handle (q.v.)) know when it's necessary to call * Browser::UpdateMenuBar(). */ return (menubarNeedsUpdating or fileSubmenuListNeedsUpdating); } #ifdef GRAPHICS void RSLBrowser::OpenInitGraphicsFiles() { const char* gfn; while (gfn = EnumGFiles()) { GetLiveWin()->GetIdraw()->GetEditor()->OpenNew(gfn); } } #endif bool RSLBrowser::RescanFailed() { return rescanfailed; } RSLMenuBar* RSLBrowser::UpdateMenuBar(EntityStruct* es) { /* * Do Step 1 above. */ if (fileSubmenuListNeedsUpdating) { if (addedFile != null) { menuBar->AddToFileMenuList(addedFile); addedFile = null; } if (deletedFile != null) { menuBar->DeleteFromFileMenuList(deletedFile); deletedFile = null; } fileSubmenuListNeedsUpdating = false; } if (not menubarNeedsUpdating) return menuBar; if (not es) { menuBar->UpdateModuleMenuBar(es); menubarNeedsUpdating = false; return menuBar; } switch (es->GetSym()->Class) { case C_Obj: menuBar->UpdateObjMenuBar(es); break; case C_Op: menuBar->UpdateOpMenuBar(es); break; case C_Module: menuBar->UpdateModuleMenuBar(es); break; } menubarNeedsUpdating = false; return menuBar; } EntityStrEd* RSLBrowser::UpdateEntityName(EntityStruct* es) { /* * Do step 2 above. */ char* name = es->GetName(); char* fullName = new char[strlen(name) + strlen("operation ")]; /* * Concat the symbol class on the front of the name. */ switch (es->GetSym()->Class) { case C_Obj: sprintf(fullName, "object %s", name); break; case C_Op: sprintf(fullName, "operation %s", name); break; case C_Module: sprintf(fullName, "module %s", name); break; } /* * Stick in the new name. */ curEntity->Message(fullName); return curEntity; } FilenameStrEd* RSLBrowser::UpdateFileName(EntityStruct* es) { /* * Do step 3 above. */ curFile->Message(es->GetSym()->Loc.file); return curFile; } EntityStrBrowserPair* RSLBrowser::UpdateStrBrowsers(EntityStruct* es) { /* * Do step 4 above. */ return entBrowsers->ScrollToName(es); } EntityTextEdList* RSLBrowser::UpdateText(EntityStruct* es) { /* * Do step 5 above. */ codeEds->ScrollToName(es); world->Raise(codeEds->CurEd()); return codeEds; } RSLBrowser* RSLBrowser::UpdateEdDuringEdit(char* filename) { /* * Change the current editor during edit mode. This is called from * Sted::Handle, q.v. */ if (editMode) { codeEds->MakeCur(codeEds->Find(filename)->GetData()); curFile->Message(filename); } return this; } RSLBrowser* RSLBrowser::InstallNames() { /* * Fill in the modules menu and the two entity browsers. The necessary * info comes from the translator in exactly the form we need -- three * sorted aux string lists that contain modules, objs, and ops resp. We * simply pass these lists on to the lower-level installers in the * modules menu and the entity browsers. * * As explained elsewhere, the entries on the list contain an RSL name as data * and the symtab entry for the name as auxdata. Since string list elems and * entity structs are compatible, we can treat them the same here. I.e., * what's a StrListElem in the translator is an EntitySturct to us here, * without any data conversion required. * * Design note: We might want to call entBrowsers->*->Append rather than * entBrowsers->*->InstallNames. Given the interspersion, this would allow us * to traverse the list just once, rather than once + third again + third again * + third again = twice. The reason we dont use the one pass technique is * that the str browsers need to keep their own separate ent lists, since we * cant easily specialize the the elems of a string browser to be * EntityStructs, rather than char*s. Get it? * * Note that we could in fact call Include on the modules menu incrementally, * since menu items can be specialized to EntityStructs. However, we go ahead * with the non-incremental method, since we have to do it for the str browsers * anyway, and the modules list is likely to be reasonably short. * * We may want to revisit this decision if it turns out that all the list * traversing actually slows things down. We'll see. */ EntityStruct* es; /* * Get the goods from the translator interface. */ BrowserSymLists* allsyms = ti->GetAllSyms(); /* * Hand the lists over to the appro installers. */ menuBar->InstallModules((EntityStructList*) allsyms->mods); entBrowsers->InstallObjs((EntityStructList*) allsyms->objs); entBrowsers->InstallOps((EntityStructList*) allsyms->ops); return this; } void RSLBrowser::ErrorDialog(char* msg) { ButtonState* bs = new ButtonState(1); HBox* hbox = new HBox; VBox* vbox = new VBox; vbox->Align(Center); vbox->Insert(new VGlue(round(0.25 * inch))); vbox->Insert(new Message(msg)); vbox->Insert(new VGlue(round(0.25 * inch))); vbox->Insert( new PushButton(" OK ", bs, 1)); vbox->Insert(new VGlue(round(0.25 * inch))); hbox->Insert(new HGlue(round(0.25 * inch))); hbox->Insert(vbox); hbox->Insert(new HGlue(round(0.25 * inch))); Dialog* dialog = new Dialog(bs, new ShadowFrame(hbox)); world->InsertTransient(dialog, this, 500, 500, Center); dialog->Accept(); world->Remove(dialog); } bool RSLBrowser::ChooseDialog(char* msg) { ButtonState* bs = new ButtonState(1); HBox* hbox = new HBox; VBox* vbox = new VBox; vbox->Align(Center); vbox->Insert(new VGlue(round(0.25 * inch))); vbox->Insert(new Message(msg)); vbox->Insert(new VGlue(round(0.25 * inch))); vbox->Insert( new HBox( new PushButton(" OK ", bs, 1), new HGlue(round(0.50 * inch)), new PushButton(" Cancel ", bs, 2))); vbox->Insert(new VGlue(round(0.25 * inch))); hbox->Insert(new HGlue(round(0.25 * inch))); hbox->Insert(vbox); hbox->Insert(new HGlue(round(0.25 * inch))); Dialog* dialog = new Dialog(bs, new ShadowFrame(hbox)); world->InsertTransient(dialog, this, 500, 500, Center); dialog->Accept(); world->Remove(dialog); int v; bs->GetValue(v); return (v==1) ? true : false; } char* RSLBrowser::ChooseStringDialog(char* msg) { ButtonState* bs = new ButtonState(1); LStringBrowser* sb = new LStringBrowser(new ButtonState(), 10, 45); HBox* hbox = new HBox; VBox* vbox = new VBox; vbox->Align(Center); vbox->Insert(new VGlue(round(0.25 * inch))); vbox->Insert(new Message(msg)); vbox->Insert(new HBox( sb, new VScroller(sb))); /*while (Enum*/ vbox->Insert(new VGlue(round(0.25 * inch))); vbox->Insert( new HBox( new PushButton(" OK ", bs, 1), new HGlue(round(0.50 * inch)), new PushButton(" Cancel ", bs, 2))); vbox->Insert(new VGlue(round(0.25 * inch))); hbox->Insert(new HGlue(round(0.25 * inch))); hbox->Insert(vbox); hbox->Insert(new HGlue(round(0.25 * inch))); Dialog* dialog = new Dialog(bs, new ShadowFrame(hbox)); world->InsertTransient(dialog, this, 500, 500, Center); dialog->Accept(); world->Remove(dialog); int v; bs->GetValue(v); return (v==1) ? sb->String(sb->Selection()) : null; } UndefEntityDialog::UndefEntityDialog(ButtonState* bs) : Dialog(bs, new ShadowFrame()) { HBox* hbox = new HBox; VBox* vbox = new VBox; stred = (new StringEditor(state, " ")); vbox->Align(Center); vbox->Insert(new VGlue(round(0.25 * inch))); vbox->Insert(stred); vbox->Insert(new VGlue(round(0.25 * inch))); vbox->Insert( new PushButton(" OK ", bs, 1)); vbox->Insert(new VGlue(round(0.25 * inch))); hbox->Insert(new HGlue(round(0.25 * inch))); hbox->Insert(vbox); hbox->Insert(new HGlue(round(0.25 * inch))); ((ShadowFrame*)component)->Insert(hbox); } bool UndefEntityDialog::Popup(const char* message, World* w) { /*World* w = GetWorld();*/ bool accept; Event e; e.x = 300; e.y = 300; e.target = this; stred->Message(message); /* return Dialog::Popup(e); */ w->InsertTransient(this, e.target, 500, 500, align); accept = Accept(); w->Remove(this); return accept; } void RSLBrowser::AddArg(const char* arg) { if (argc < numargs) { char* newarg = argv[argc++] = newstr(arg); if (IsSwitch(arg)) { ProcessCommandLineSwitch(arg); } #ifdef GRAPHICS else if (IsGraphicsFile(arg)) { gfilelist->Put(new StrListElem(newarg, null)); } #endif else { tiargv[tiargc++] = newarg; tfilelist->Put(new StrListElem(newarg, null)); deletedFile = null; addedFile = newstr(newarg); fileSubmenuListNeedsUpdating = true; } } else { char buf[100]; sprintf(buf, "No more than %d files can be open at once.", numargs); ErrorDialog(buf); } } bool RSLBrowser::IsSwitch(const char* arg) { return arg[0] == '-'; } bool RSLBrowser::IsTextFile(const char* arg) { int l = strlen(arg); if (l < 4) return false; return ((arg[l-4] == '.') and (arg[l-3] == 'r') and (arg[l-2] == 's') and (arg[l-1] == 'l')); } bool RSLBrowser::IsGraphicsFile(const char* arg) { int l = strlen(arg); if (l < 4) return false; return ((arg[l-4] == '.') and (arg[l-3] == 'r') and (arg[l-2] == 's') and (arg[l-1] == 'g')); } bool RSLBrowser::IsTransFile(const char* arg) { return true; } void RSLBrowser::DeleteArg(const char* arg) { /* * Remove the given arg from argv and the file list if it's a file. */ int i; for (i = 1; i < argc; i++) { if (argv[i] and streq(argv[i], arg)) break; } for (i++; i < argc; i++) { argv[i-1] = argv[i]; } argc--; if (arg[0] == '-') { /* TODO */ } else { tfilelist->DelNth(tfilelist->FindPos(arg)); // if (addedFile) // delete addedFile; addedFile = null; // if (deletedFile) // delete deletedFile; deletedFile = newstr(arg); fileSubmenuListNeedsUpdating = true; } } void RSLBrowser::DisableBrowsing() { /* * After unsuccessful translation check (in Rescan) or entering edit mode, turn * all browsing off. This entails emptying the modules pulldown, and * everything else visible in the display. A disabled flag is also set so that * other things, like typing in the streds, is disabled. Note thate there is * no explicit function to reenable browsing. This is done in Rescan(), q.v. */ menuBar->InstallModules((EntityStructList*) 0); entBrowsers->InstallObjs((EntityStructList*) 0); entBrowsers->InstallOps((EntityStructList*) 0); menubarNeedsUpdating = true; curEntity->Message(""); curFile->Message(""); es = null; /* * Note: The menubar will be reset to the initial menubar (with entity * browsing menus) subsequently. Here's how: MenubarNeedsUpdating is * responded to in RSLBrowser::Run, which in turn calls UpdateMenuBar(es), * which sees es == null, which causes it to call UpdateModulesMenu, * which gets us to the cleaned-out menu we're after. */ } void RSLBrowser::IncrEdPos() { /* * Bump the editor x,y pos by a reasonable amout, up to a reasonable * value, and then stop bumping. */ edx += 17; edy -= 17; if ((edx < 400) and (edy < 17)) { edx = 400; edy = 260; } else if ((edx >= 400 ) and (edy < 17)) { edx -= 17; edy += 17; } } int RSLBrowser::GetEdX(){ /* * Return the current ed x position. */ return edx; } int RSLBrowser::GetEdY() { /* * Return the current ed y position. */ return edx; }