pkg://HexEd-1.10-src.tar.gz:424274/
HexEd-1.10/
hexed/hexed.cc
downloads
/*****************************************************************************/
/* */
/* HEXED.CC */
/* */
/* (C) 1995-96 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@ibb.schwaben.com */
/* */
/*****************************************************************************/
// $Id$
//
// $Log$
//
//
#include "eventid.h"
#include "environ.h"
#include "filepath.h"
#include "program.h"
#include "progutil.h"
#include "menuitem.h"
#include "menue.h"
#include "stdmenue.h"
#include "stdmsg.h"
#include "filesel.h"
#include "winmgr.h"
#include "settings.h"
#include "hexobjid.h"
#include "hexmsg.h"
#include "hexopt.h"
#include "hexwin.h"
#include "hexed.h"
/*****************************************************************************/
/* Message constants */
/*****************************************************************************/
const u16 msHexed = MSGBASE_HEXED + 0;
const u16 msAbout = MSGBASE_HEXED + 1;
const u16 msQuit = MSGBASE_HEXED + 2;
const u16 msFile = MSGBASE_HEXED + 3;
const u16 msOpen = MSGBASE_HEXED + 4;
const u16 msClose = MSGBASE_HEXED + 5;
const u16 msWindow = MSGBASE_HEXED + 6;
const u16 msTile = MSGBASE_HEXED + 7;
const u16 msCascade = MSGBASE_HEXED + 8;
const u16 msWindowList = MSGBASE_HEXED + 9;
const u16 msOptions = MSGBASE_HEXED + 10;
const u16 msEditOptions = MSGBASE_HEXED + 11;
const u16 msSaveOptions = MSGBASE_HEXED + 12;
const u16 msZoom = MSGBASE_HEXED + 13;
const u16 msResize = MSGBASE_HEXED + 14;
const u16 msSearch = MSGBASE_HEXED + 15;
const u16 msGoto = MSGBASE_HEXED + 16;
const u16 msCloseAll = MSGBASE_HEXED + 17;
const u16 msRedraw = MSGBASE_HEXED + 18;
const u16 msSave = MSGBASE_HEXED + 19;
const u16 msSaveAll = MSGBASE_HEXED + 20;
const u16 msSaveOptionsError = MSGBASE_HEXED + 30;
const u16 msOptionsSaved = MSGBASE_HEXED + 31;
const u16 msAboutInfo = MSGBASE_HEXED + 32;
const u16 msWrongArg = MSGBASE_HEXED + 33;
const u16 msOpenFile = MSGBASE_HEXED + 34;
const u16 msSettingsFileError = MSGBASE_HEXED + 35;
/*****************************************************************************/
/* class HexedApp */
/*****************************************************************************/
HexedApp::HexedApp (int argc, char* argv []):
Program (argc, argv, CreateMenueBar, CreateStatusLine, "hexed"),
#if defined(DOS) || defined(DOS32) || defined(OS2)
SettingsFile (SupportPath + "hexed.rc") // Use EXE directory
#else
SettingsFile (MakeAbsolute ("~/.hexedrc")) // Use home dir
#endif
{
// Remember if windows added from the command line
int CmdLineWindows = 0;
// Open the program option file
if (!SettingsFile.IsEmpty ()) {
// Ignore errors for now
if (StgOpen (SettingsFile) != 0) {
ErrorMsg (LoadAppMsg (msSettingsFileError));
}
}
// Get the options from the settings file, if none exists, create a new
// options object
HexOpt = (HexedOptions*) StgGet ("Options");
if (HexOpt == NULL) {
// Does not exist, create default options
HexOpt = new HexedOptions;
}
// Set the edit mode default from the options
DefaultEditMode = (EditMode) HexOpt->GetDefaultMode ();
// Load the window manager from the settings file
if (HexOpt->ReloadFiles ()) {
// Reload wanted, try to load the window manager
WinMgr = (WindowManager*) StgGet ("WinMgr");
}
if (WinMgr == NULL) {
// Does not exist or no reload, create default
WinMgr = new WindowManager;
}
// Parse the command line
Rect Bounds = Background->OuterBounds ();
Bounds.Grow (0, -4);
unsigned I = 1;
while (I < argc) {
char* Item = argv [I];
if (*Item == '-') {
switch (Item [1]) {
case 'm':
switch (Item [2]) {
case 'h':
DefaultEditMode = emHex;
break;
case 'a':
DefaultEditMode = emASCII;
break;
case 's':
DefaultEditMode = emShow;
break;
case 'r':
DefaultEditMode = emReadonly;
break;
default:
ArgumentError (Item);
break;
}
break;
default:
ArgumentError (Item);
break;
}
} else {
// Filename, create a new edit window if opening files is still
// allowed
if (MainMenue->ItemWithID (miOpen)->IsActive ()) {
// Create the window
NewWindow (MakeAbsolute (Item), Bounds);
// Remember that we added a window
CmdLineWindows++;
}
}
// Next argument
I++;
}
// Make a window cascade if we added new windows
if (CmdLineWindows > 0) {
WinMgr->Cascade ();
}
// Ok, initialization is complete, post an apropriate event
::PostEvent (evInit);
}
HexedApp::~HexedApp ()
// Destruct an application object
{
// Post an event before shutting down
::PostEvent (evExit);
// Delete the window manager, including all windows
delete WinMgr;
// Delete the option object
delete HexOpt;
// Close the settings file
StgClose ();
}
void HexedApp::ArgumentError (const char* Arg)
// Print an error message
{
ErrorMsg (FormatStr (App->LoadAppMsg (msWrongArg).GetStr (), Arg));
}
void HexedApp::DisableStatusItem (u32 ItemFlag)
// Disable the statusline text corresponding to ItemFlag
{
if (StatusFlags & ItemFlag) {
StatusFlags &= ~ItemFlag;
StatusLine->Replace (StatusFlags);
}
}
void HexedApp::EnableStatusItem (u32 ItemFlag)
// Enable the statusline text corresponding to ItemFlag
{
if ((StatusFlags & ItemFlag) == 0) {
StatusFlags |= ItemFlag;
StatusLine->Replace (StatusFlags);
}
}
void HexedApp::DisableCommand (i16 ID)
// Disable the command bound to the menue item with the given ID
{
// Gray the item
MainMenue->GrayItem (ID);
// Get the accel key of the item
Key AccelKey = MainMenue->GetAccelKey (ID);
// If this key is registered, unregister it
if (AccelKey != kbNoKey && KeyIsRegistered (AccelKey)) {
UnregisterKey (AccelKey);
}
// Check if the removed command has an entry in the status line
switch (ID) {
case miClose:
DisableStatusItem (siAltF3_Close);
break;
case miOpen:
DisableStatusItem (siF3_Open);
break;
}
}
void HexedApp::EnableCommand (i16 ID)
// Enable the command bound to the menue item with the given ID
{
// Enable the item
MainMenue->ActivateItem (ID);
// Get the accel key of the item
Key AccelKey = MainMenue->GetAccelKey (ID);
// If this key is not registered, do it
if (AccelKey != kbNoKey && KeyIsRegistered (AccelKey) == 0) {
RegisterKey (AccelKey);
}
// Check if the removed command has an entry in the status line
switch (ID) {
case miClose:
EnableStatusItem (siAltF3_Close);
break;
case miOpen:
EnableStatusItem (siF3_Open);
break;
}
}
void HexedApp::HandleEvent (Event& E)
// Handle incoming events.
{
// Call the derived function and return if the event is handled
Program::HandleEvent (E);
if (E.Handled) {
return;
}
// Now look at the event code
switch (E.What) {
case evWinMgrNoWindows:
// No more open windows
DisableCommand (miClose);
DisableCommand (miSave);
DisableCommand (miSaveAll);
DisableCommand (miZoom);
DisableCommand (miResize);
DisableCommand (miTile);
DisableCommand (miCascade);
DisableCommand (miCloseAll);
DisableCommand (miSearch);
DisableCommand (miGoto);
break;
case evWinMgrFirstOpen:
// One open window
EnableCommand (miClose);
EnableCommand (miSave);
EnableCommand (miSaveAll);
EnableCommand (miZoom);
EnableCommand (miResize);
EnableCommand (miTile);
EnableCommand (miCascade);
EnableCommand (miCloseAll);
EnableCommand (miSearch);
EnableCommand (miGoto);
break;
case evWinMgrLastClose:
// Max count - 1 reached
EnableCommand (miOpen);
break;
case evWinMgrMaxWindows:
// Max count of windows reached
DisableCommand (miOpen);
break;
case evEnableCommand:
EnableCommand ((i16) E.Info.U);
break;
case evDisableCommand:
DisableCommand ((i16) E.Info.U);
break;
}
}
static MenueBarItem* GetMenueBarItem (u16 MsgID, i16 ItemID,
WindowItem* MenueList,
WindowItem* NextItem)
{
return new MenueBarItem (App->LoadAppMsg (MsgID), ItemID, MenueList, NextItem);
}
static MenueItem* GetMenueItem (u16 MsgID, i16 ItemID, Key AccelKey, WindowItem* NextItem)
{
return (MenueItem*) SetAccelKey (new MenueItem (App->LoadAppMsg (MsgID),
ItemID,
NextItem),
AccelKey);
}
static MenueLine* GetMenueLine (WindowItem* NextItem)
{
return new MenueLine (miNone, NextItem);
}
TopMenueBar* HexedApp::CreateMenueBar ()
{
TopMenueBar* M = new TopMenueBar (
GetMenueBarItem (msHexed, miHexed,
GetMenueItem (msAbout, miAbout, kbNoKey,
NULL
),
GetMenueBarItem (msFile, miFile,
GetMenueItem (msOpen, miOpen, vkOpen,
GetMenueItem (msSave, miSave, vkSave,
GetMenueItem (msSaveAll, miSaveAll, kbNoKey,
GetMenueLine (
GetMenueItem (msSearch, miSearch, kbMetaS,
GetMenueItem (msGoto, miGoto, kbMetaP,
GetMenueLine (
GetMenueItem (msQuit, miQuit, vkQuit,
NULL
)))))))),
GetMenueBarItem (msWindow, miWindow,
GetMenueItem (msTile, miTile, kbNoKey,
GetMenueItem (msCascade, miCascade, kbNoKey,
GetMenueItem (msCloseAll, miCloseAll, kbNoKey,
GetMenueItem (msRedraw, miRedraw, kbNoKey,
GetMenueLine (
GetMenueItem (msZoom, miZoom, vkZoom,
GetMenueItem (msResize, miResize, vkResize,
GetMenueItem (msClose, miClose, vkClose,
GetMenueLine (
GetMenueItem (msWindowList, miWindowList, kbMeta0,
NULL
)))))))))),
GetMenueBarItem (msOptions, miOptions,
GetMenueItem (msEditOptions, miEditOptions, kbNoKey,
GetMenueItem (msSaveOptions, miSaveOptions, kbNoKey,
NULL
)),
NULL
)))));
// Register the accel keys of the submenues
App->RegisterKey (M->GetAccelKey (miHexed));
App->RegisterKey (M->GetAccelKey (miFile));
App->RegisterKey (M->GetAccelKey (miWindow));
App->RegisterKey (M->GetAccelKey (miOptions));
// Register the accel keys and gray unused items
App->RegisterKey (M->GetAccelKey (miQuit));
App->RegisterKey (M->GetAccelKey (miOpen));
App->RegisterKey (M->GetAccelKey (miWindowList));
M->GrayItem (miSave);
M->GrayItem (miSaveAll);
M->GrayItem (miCloseAll);
M->GrayItem (miClose);
M->GrayItem (miZoom);
M->GrayItem (miResize);
M->GrayItem (miSearch);
M->GrayItem (miGoto);
M->GrayItem (miTile);
M->GrayItem (miCascade);
// Return the result
return M;
}
BottomStatusLine* HexedApp::CreateStatusLine ()
{
const u32 Flags = siExit | siOpen;
((HexedApp*) App)->StatusFlags = Flags;
return new BottomStatusLine (Flags);
}
HexedWin* HexedApp::NewWindow (const String& Filename, const Rect& Bounds)
// Add a new hexed window to the window manager
{
// Remember the file name for the next time
LastFile = Filename;
// Try to construct a new HexedWin
HexedWin* Win = new HexedWin (Bounds, Filename);
if (Win->HadError ()) {
delete Win;
return NULL;
}
// Insert the window into the winmgr
if (WinMgr->AddWindow (Win) == NULL) {
// Some error (probably too many windows)
delete Win;
return NULL;
} else {
// No error
return Win;
}
}
HexedWin* HexedApp::NewWindow ()
// Get a file name from the user and insert the given window into the list
{
// Create a file selector
FileSelector FS (LoadAppMsg (msOpenFile), "");
// Get a selection
String Name = FS.GetChoice ();
// Bail out on abort
if (Name.IsEmpty ()) {
return NULL;
}
// Calculate the window bounds
Rect Bounds = Background->OuterBounds ();
Bounds.A.Y++;
Bounds.B.Y -= 5;
// Create a window and insert it
return NewWindow (Name, Bounds);
}
void HexedApp::Zoom (ItemWindow* Win)
// Zoom a window
{
if (Win && Win->CanResize ()) {
Win->Zoom ();
}
}
void HexedApp::Resize (ItemWindow* Win)
// Resize a window
{
if (Win) {
Win->MoveResize ();
}
}
void HexedApp::Close (ItemWindow* Win)
// Close a window
{
if (Win) {
WinMgr->DeleteWindow (Win);
}
}
void HexedApp::Search (ItemWindow* Win)
// Search a string in a window make shure, it's really a hexed window
{
if (Win) {
CHECK (Win->StreamableID () == ID_HexedWin);
((HexedWin*) Win)->Search ();
}
}
void HexedApp::Goto (ItemWindow* Win)
// Goto a specific position in file, make shure,
{
if (Win) {
CHECK (Win->StreamableID () == ID_HexedWin);
((HexedWin*) Win)->Goto ();
}
}
int HexedApp::Run ()
{
// If we have already windows open, edit the topmost window
if (WinMgr->WindowCount () > 0) {
WinMgr->Browse (WinMgr->GetTopWindow ());
}
// Activate the main menue
MainMenue->Activate ();
// Main loop
Key K;
while (!Quitting ()) {
// Switch according to the users choice
switch (MainMenue->GetChoice ()) {
case miAbout:
InformationMsg (LoadAppMsg (msAboutInfo));
break;
case miOpen:
WinMgr->Browse (NewWindow ());
break;
case miClose:
Close (WinMgr->GetTopWindow ());
break;
case miSearch:
Search (WinMgr->GetTopWindow ());
break;
case miGoto:
Goto (WinMgr->GetTopWindow ());
break;
case miQuit:
// End the program
if (AskReallyQuit () == arYes) {
// Allow saving window changes
if (WinMgr->CanClose ()) {
// Auto save the options if requested
if (HexOpt->AutoSave ()) {
StgPut (HexOpt, "Options");
}
// Save the window manager, then close all windows
StgPut (WinMgr, "WinMgr");
WinMgr->CloseAll ();
Quit = 1;
}
}
break;
case miZoom:
Zoom (WinMgr->GetTopWindow ());
break;
case miResize:
Resize (WinMgr->GetTopWindow ());
break;
case miTile:
WinMgr->Tile ();
break;
case miCascade:
WinMgr->Cascade ();
break;
case miCloseAll:
WinMgr->CloseAll ();
break;
case miRedraw:
RedrawScreen ();
break;
case miWindowList:
WinMgr->Browse (WinMgr->ChooseWindow ());
break;
case miEditOptions:
HexOpt->Edit ();
break;
case miSaveOptions:
StgPut (HexOpt, "Options");
InformationMsg (LoadAppMsg (msOptionsSaved));
break;
case 0:
K = MainMenue->GetAbortKey ();
if (K != vkAbort) {
// Window hotkey
WinMgr->Browse (WinMgr->FindWindowWithKey (K));
}
break;
}
}
return 0;
}
int main (int argc, char* argv [])
{
// Declare an application object
HexedApp MyApp (argc, argv);
// Use it...
int Result = MyApp.Run ();
// Return the result
return Result;
}