/* * Class RSLBrowser is the main dude. It's a scene containing the six * top-level interactors: command menubar, cur entity name, cur entity file, * obj str browser, op str browser, text ed list, and graphics ed. The * graphics ed in turn manages its own subwindows. See the users manual for * further description of these items. * * The major job for RSLBrowser is to update the context of the display when * the currently selected entity changes. The steps for this updating are * descirbed in detail in comments that follow. */ #ifndef browserIncluded #define browserIncluded #include #include #include #include #include #include "std-macros++.h" #include "exception.h" #include "menus.h" #include "menudialogs.h" #include "rstred.h" #include "rstrbrowser.h" #include "rtexted.h" #include "gred.h" #include "trans-interface.h" #include "entity.h" #include "strlist.h" #ifdef GRAPHICS #include "editor.h" #include "idraw.h" #include "window.h" #include "windowaccess.h" #endif class EntityStrBrowserPair; class RSLMenuBar; class EntityStrEd; class FilenameStrEd; class UndefEntityDialog; /* * Constants. */ static const int numargs = 100; /* Max number of trans args */ class RSLBrowser : public MonoScene { public: RSLBrowser(TransInterface* ti, World* world, int argc, char** argv, exception* exitExc); /* * Call Init thence Layout to construct. The given TransInterface lets * us chat with the RSL translator as necessary. */ RSLBrowser* UpdateCurEntity(EntityStruct* es); /* * Update the state of the browser to make the given entity current. * This entails the following steps: * * 1. Update the menus in the menubar to contain the info appro for * the new entity. * * 2. Display the entity name in the 'Selected Entity' str editor. * * 3. Display the file in which the entity is def'd in the 'File' str * editor. * * 4. Scroll to and highlight the entity name in the appro entity * string browser, if not there already; unhighlight the other * entity string browser. (We'll be there already if the update * was initiated by clicking in one of the str browsers. If this * is the case, this step will just be a noop.) * * 5. Scroll to and highlight the entity name in the appropriate * window. This includes exposeing the text window if necessary. * * 6. Update the graphics display if there is one and 'Auto Graphics' * is on. */ RSLBrowser* UpdateCurEntity(const char* ename); /* * Version of UpdateCurEntity that takes a 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*). */ RSLBrowser* GotoPicture(const char* ename); /* * Given a picture name, tell the graphic browser to make it current. */ 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. */ RSLBrowser* ExitEditMode(); /* * Reenable browsing and disable editing. */ RSLBrowser* ToggleEditBrowseMode(); RSLBrowser* EnterTransientMenus(); RSLBrowser* ExitTransientMenus(); RSLBrowser* ToggleTransientMenusMode(); RSLBrowser* EnterAutoGraphicsMode(); RSLBrowser* ToggleAutoGraphicsMode(); RSLBrowser* ExitAutoGraphicsMode(); RSLBrowser* SetTransFlags(StrList* flags); bool 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. */ RSLBrowser* Open(const char* filename); /* * Call the translator on the given file. If an error occurs, put up an * error box, and do nothing to the current state of the browser. If no * error occurs, add the chosen file to the list of the current files and * retranslate the whole wod. Update the contents of the entity str * browsers, but leave the current entity unchanged. */ 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. */ private: bool OpenNew(const char* filename); /* * Check the biznis about reading, writing, what have you. */ public: RSLBrowser* Close(const char* filename); /* * Close the given file and remove the editor in which it resides. */ RSLBrowser* Expose(const char* filename); /* * Expose the ed in which the given file resides. */ RSLBrowser* Save(); /* * Save file in cur ed. */ RSLBrowser* SaveAs(const char* filename); /* * Save given file in cur ed. */ RSLBrowser* SaveAll(); EntityTextEd* CurEd(); /* * Just pass through codeEds->CurEd(). */ private: RSLBrowser* Init2(); void ProcessCommandLineArgs(int argc, char** argv); /* * Sort out command-line files and switches. As they are sorted, the * files and switches destined for the translator are copied into the * local members targc and tiargs. Translator files are those with any * extension other than .rsg. Graphics files (.rsg) are opened * immediately if the graphic browser is enabled. Non-translator * switches are processed appropriately. All other switches are * designated bogus. If the command-line bogosity threshold is exceeded, * the system establishes an EFT link to the user's largest bank account * and debits the account by $1000. */ void ProcessCommandLineSwitch(const char* arg); /* * Do what the command line switch says to do. */ bool IsSwitch(const char* arg); /* * True if arg is a switch (i.e., starts with '-'). */ bool IsTransSwitch(const char* arg); /* * True if arg is a switch to be processed by the rsl translator. */ bool IsTransFile(const char* arg); /* * Always true at this point, but may be pickier at some future date. */ bool IsTextFile(const char* arg); /* * True if arg ends in ".rsl" extension. */ bool IsGraphicsFile(const char* arg); /* * True if arg ends in ".rsg" extension. */ RSLBrowser* Save(EntityTextEd* ed); /* * Save file in given ed. */ RSLBrowser* SaveAs(EntityTextEd* ed, const char* filename); /* * Save given file in given ed. */ void SaveAsLoop(EntityTextEd* ed); /* * Go round and round until user selects a writeable file or gives up. */ public: RSLBrowser* SearchForw(const char* searchstring); /* * Call the texted to do the search in the current ed. */ RSLBrowser* SearchBack(const char* searchstring); /* * Ibid. */ RSLBrowser* GotoLine(int line); /* * Goto the specified line in the current editor. */ RSLBrowser* NewEditor(const char* filename = null); /* * Create a new, detached, text ed window and make it current. Its * contents are intially empty. */ bool InEditMode(); /* * Return true if currenly in edit mode, false otherwise. Used by Exit, * among possibly others. */ bool InTransientMenusMode(); bool InAutoGraphicsMode(); RSLBrowser* Edit(char* path); /* * Open the given path in the current ed, if it's not already. */ void CheckExit(); /* * Check if anything needs to be saved and/or cleaned up before exit. */ void LayoutScreen(); /* * Stick this into the upper left corner of the screen and pile the text * eds up neatly below. */ void Run(); /* * We need our own version of Run because of a subtlety in menubar * updating. Viz., when we select a new entity from, say, the Components * pulldown, this leads to an update of the menubar, among other updates. * This in turn leads to clearing of the current menubar, which removes * all of the items in the menubar puldowns. But this wont do, since at * the time this clearing occurs, we're still in the Do function for the * Components pulldown menu item that initiated the updating. And when * we return from this invocation of NameListMenuItem::Do, the menubar * context in which we were running has been nuked via the earlier * clearing. What specifically transpires is an error in some member * function of Control when it tries to access the defunct context. * * As a result of all of this, we need to wait until the * NameListMenuItem::Do has returned before we update the menubar. This * is accomplished by setting a flag in UpdateCurEntity rather than * calling UpdateMenuBar directly. This flag indicates that the menubar * needs updating, which updating will be performed in the Run loop. */ bool 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(). */ void OpenInitGraphicsFiles(); /* * Tell the graphics ed to open .rsg files that were specified explicitly * or implicitly in the command line. This needs to be done in a * separate function since the files cannot be opened as they are * encounted since the graphics ed isnt up yet at that time. Hence, this * function gets called a liitle later, in main.c, q.v.. */ bool RescanFailed(); /* * Tell who may need to know that whether the most recent ReScan failed * or succeeded. Used in particular (and perhaps only) by * menus.c:EditBrowsMenuItem::Do, q.v., for reasons explained there. */ private: bool menubarNeedsUpdating; bool fileSubmenuListNeedsUpdating; /* * Special flags. See comment at Run above. These flags used to be * public, since the crappy event handling cheesed me off and I let * EntityStrBrowser::Handle (q.v.) see them directly. Now access is * encapsulated in the public function MenubarNeedsUpdating(), but I'm * still non-plussed by the event handling mess. */ char* addedFile; char* deletedFile; RSLMenuBar* menuBar; /* * Top-level menubar. */ public: RSLMenuBar* UpdateMenuBar(EntityStruct* es); /* * Do step 1 above. Public for same reason that MenubarNeedsUpdating is. */ RSLBrowser* UpdateEdDuringEdit(char* filename); /* * Change the current editor during edit mode. This is called from * Sted::Handle, q.v. */ void ErrorDialog(char* msg); /* * Popup a dialog box with an error message and an OK button to dismiss * it. Use has no choice other than to press OK. */ bool ChooseDialog(char* msg); /* * Popup a dialog box with an error message and OK and Cancel buttons. * If user presses OK, then return true; if user presses Cancel, return * false. With either press, dialog box is dismissed. */ char* ChooseStringDialog(char* msg); /* * Popup a dialog box with a message, OK and Cancel buttons, and a string * chooser. If user presses OK, then return the chosen string, or null * if no string is chosen; if user presses Cancel, return null. With * either press, dialog box is dismissed. */ bool ObjIsCur(); /* * Return true if the current entity is an object. */ bool OpIsCur(); /* * Return true if the current entity is an operation. */ const char* EnumTFiles(); /* * Enumerate the text open files. */ const char* EnumGFiles(); /* * Enumerate the graphics open files. */ World* GetWorld() {return world;} private: /*** * Private functions */ EntityStrEd* UpdateEntityName(EntityStruct* es); /* * Do step 2 above. */ FilenameStrEd* UpdateFileName(EntityStruct* es); /* * Do step 3 above. */ EntityStrBrowserPair* UpdateStrBrowsers(EntityStruct* es); /* * Do step 4 above. */ EntityTextEdList* UpdateText(EntityStruct* es); /* * Do step 5 above. */ EntityTextEdList* UpdateGraphics(EntityStruct* es); /* * Do step 6 above. */ 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. */ Interactor* 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 * element. */ Box* Layout(); /* * Handle the UI layout details. */ Interactor* LayoutStrEds(); Interactor* LayoutStrBrowsers(); void LayoutTextEds(); void AddArg(const char* arg); /* * Tack the given arg onto the local copy of argv and bump the local * argc. If the arg is a translator file (anything but .rsg), stick in * on the trans file list. If it's a grapihcs file (.rsg), send it to * the graphics browser to be opened. Otherwise process it as a command * line switch. */ void DeleteArg(const char* arg); /* * Remove the given arg from argv and the file list if it's a file. */ void DisableBrowsing(); /* * After unsuccessful translation check (in Rescan), turn all browsing * off. This entails emptying the modules pulldown and both of the * entity str browsers. Note thate there is no explicit function to * reenable browsing. This is done by in Rescan(), q.v. */ void IncrEdPos(); /* * Bump the editor x,y pos by a reasonable amout, up to a reasonbable * value, and then stop bumping. Return the unbumped value. */ int GetEdX(); /* * Return the current ed x position. */ int GetEdY(); /* * Return the current ed y position. */ /*** * Private data */ EntityStrEd* curEntity; /* Display of cur entity by name*/ FilenameStrEd* curFile; /* Display of cur entity's filename */ EntityStrBrowserPair* entBrowsers; /* Str browsers of entity names */ EntityTextEdList* codeEds; /* Code browsing editor(s) */ EntityGraphicEd* graphicEd; /* Companion graphics editor */ EntityStruct* es; /* The currently selected entity */ TransInterface* ti; /* The translator interface that * supplies us various things we * need.*/ int argc; /* Current num of argv's. */ char* argv[numargs]; /* Command line args. */ int tiargc; /* Num of args sent to rsl trans. */ char* tiargv[numargs]; /* Trans command line args. */ StrList* tfilelist; /* List of current text files */ StrList* gfilelist; /* List of current graphics files */ World* world; /* Our world. */ /* * Options flags. See the users manual for details of their meanings. */ bool editMode; /* True in edit mode. */ bool transientMenus; /* True when transient menus on. */ bool autoGraphics; /* True in auto graphics mode. */ /* * Layout sizes. */ int numBrRows; /* No. of rows in entity str browsers*/ int numBrCols; /* No. of cols in entity str browsers*/ int numEdRows; /* No. of rows in resident text ed */ int numEdCols; /* No. of cols in resident text ed */ /* * Editor postioning and numbering. */ int edx; /* X pos of next text ed */ int edy; /* Y pos of next text ed */ int ednum; /* Counts eds for icon numbering. */ /* * Error handling. */ UndefEntityDialog* undefEntity; /* Dialog box to display msg */ FileDialog* filedialog; /* Choosing files after boo boos */ bool rescanfailed; /* State flag that records rescan */ }; /* * This is really obsolete now, given ErrorDialog. It's an alternative way of * handing error dialogs, of potential historical interest. */ class UndefEntityDialog : Dialog { public: UndefEntityDialog(ButtonState* bs); bool Popup(const char* message, World* w); private: StringEditor* stred; Event e; }; #endif