Загрузка данных
#include "stdafx.h"
#include "resource.h"
#include "mainframe.h"
#include "about.h"
#include "blitzide.h"
#include "libs.h"
#include <mmsystem.h>
#include <fstream>
#include <sstream>
IMPLEMENT_DYNAMIC(MainFrame, CFrameWnd)
BEGIN_MESSAGE_MAP(MainFrame, CFrameWnd)
ON_WM_CREATE()
ON_WM_DROPFILES()
ON_WM_CLOSE()
ON_WM_DESTROY()
ON_WM_ERASEBKGND()
ON_WM_SIZE()
ON_WM_ACTIVATE()
ON_COMMAND(ID_NEW, fileNew)
ON_COMMAND(ID_OPEN, fileOpen)
ON_COMMAND(ID_SAVE, fileSave)
ON_COMMAND(ID_SAVEAS, fileSaveAs)
ON_COMMAND(ID_SAVEALL, fileSaveAll)
ON_COMMAND(ID_PRINT, filePrint)
ON_COMMAND(ID_CLOSE, fileClose)
ON_COMMAND(ID_CLOSEALL, fileCloseAll)
ON_COMMAND(ID_EXIT, fileExit)
ON_COMMAND_RANGE(333, 343, fileRecent)
ON_COMMAND(ID_CUT, editCut)
ON_COMMAND(ID_COPY, editCopy)
ON_COMMAND(ID_PASTE, editPaste)
ON_COMMAND(ID_SELECTALL, editSelectAll)
ON_COMMAND(ID_FIND, editFind)
ON_COMMAND(ID_FINDNEXT, editFindNext)
ON_COMMAND(ID_REPLACE, editReplace)
ON_COMMAND(ID_CTRLTAB, ctrlTab)
ON_COMMAND(ID_CTRLSHIFTTAB, ctrlShiftTab)
ON_COMMAND(ID_ESCAPE, escape)
ON_COMMAND(ID_BACKUP, switchBackup)
ON_COMMAND(ID_QUICKHELP, quick_Help)
ON_COMMAND(ID_EXECUTE, programExecute)
ON_COMMAND(ID_REEXECUTE, programReExecute)
ON_COMMAND(ID_COMPILE, programCompile)
ON_COMMAND(ID_PUBLISH, programPublish)
ON_COMMAND(ID_COMMANDLINE, programCommandLine)
ON_COMMAND(ID_PROGRAM_PREPROCESSOR, programPreprocess)
ON_COMMAND(ID_DEBUG, programDebug)
ON_COMMAND(ID_NLAA, programNoLAA)
ON_COMMAND(ID_HOME, helpHome)
ON_COMMAND(ID_BACK, helpBack)
ON_COMMAND(ID_FORWARD, helpForward)
ON_COMMAND(ID_ABOUT, helpAbout)
ON_UPDATE_COMMAND_UI(ID_NEW, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_OPEN, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_SAVE, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_SAVEAS, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_SAVEALL, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_PRINT, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_CLOSE, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_CLOSEALL, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_CUT, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_COPY, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_PASTE, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_SELECTALL, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_FIND, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_FINDNEXT, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_REPLACE, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_EXECUTE, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_REEXECUTE, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_COMPILE, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_PUBLISH, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_COMMANDLINE, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_PROGRAM_PREPROCESSOR, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_DEBUG, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_NLAA, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_HOME, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_BACK, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_FORWARD, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_ESCAPE, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_BACKUP, updateCmdUI)
ON_UPDATE_COMMAND_UI(ID_QUICKHELP, updateCmdUI)
ON_UPDATE_COMMAND_UI_RANGE(333, 343, updateCmdUIRange)
END_MESSAGE_MAP()
enum {
TAB_INVALID, TAB_EDITOR, TAB_HTMLHELP, TAB_DEBUGLOG
};
static std::string getFile(const std::string& f) {
int n;
std::string t = f;
n = t.rfind('/'); if (n != std::string::npos) t = t.substr(n + 1);
n = t.rfind('\\'); if (n != std::string::npos) t = t.substr(n + 1);
return t;
}
static std::string getPath(const std::string& f) {
int n;
std::string t = f;
n = t.rfind('/'); if (n != std::string::npos) t = t.substr(0, n);
n = t.rfind('\\'); if (n != std::string::npos) t = t.substr(0, n);
return t;
}
MainFrame::MainFrame() :exit_flag(false) {
}
int MainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) {
CFrameWnd::OnCreate(lpCreateStruct);
this->DragAcceptFiles(TRUE);
HICON hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_MAIN_ICON));
SetIcon(hIcon, FALSE);
static HBITMAP toolbmp;
static SIZE imgsz, butsz;
static UINT toolbuts[] = {
ID_NEW,ID_OPEN,ID_SAVE,ID_CLOSE,ID_SEPARATOR,
ID_CUT,ID_COPY,ID_PASTE,ID_SEPARATOR,
ID_FIND,ID_SEPARATOR,
ID_EXECUTE,ID_SEPARATOR,
ID_HOME,ID_BACK,ID_FORWARD };
static int toolcnt = sizeof(toolbuts) / sizeof(UINT);
if (!toolbmp) {
BITMAP bm;
std::string t = prefs.homeDir + "/cfg/ide_toolbar.bmp";
toolbmp = (HBITMAP)LoadImage(0, t.c_str(), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_LOADMAP3DCOLORS);
if (!toolbmp)
{
AfxMessageBox("Toolbar failed to load!");
ExitProcess(0);
}
GetObject(toolbmp, sizeof(bm), &bm);
int n = 0;
for (int k = 0; k < toolcnt; ++k) if (toolbuts[k] != ID_SEPARATOR) ++n;
imgsz.cx = bm.bmWidth / n; imgsz.cy = bm.bmHeight;
butsz.cx = imgsz.cx + 7; butsz.cy = imgsz.cy + 6;
}
toolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_TOOLTIPS);
toolBar.SetBitmap(toolbmp);
toolBar.SetSizes(butsz, imgsz);
toolBar.SetButtons(toolbuts, toolcnt);
int style;
style = WS_CHILD | WS_VISIBLE | CBRS_ALIGN_BOTTOM;
statusBar.CreateEx(this, 0, style);
UINT IDS[] = { ID_STATUSTEXT,ID_COLROWTEXT };
statusBar.SetIndicators(IDS, 2);
statusBar.SetPaneInfo(0, ID_STATUSTEXT, SBPS_NOBORDERS | SBPS_STRETCH, 0);
statusBar.SetPaneInfo(1, ID_COLROWTEXT, 0, 128);
statusBar.SetPaneText(0, ""); statusBar.SetPaneText(1, "");
tabber.Create(WS_VISIBLE | WS_CHILD | TCS_HOTTRACK, CRect(0, 0, 0, 0), this, 1);
tabber.SetFont(&prefs.tabsFont);
tabber.setListener(this);
prefs.win_notoolbar = !prefs.win_notoolbar;
escape();
//create recent file list
CMenu menu;
menu.CreatePopupMenu();
for (int k = 0; k < prefs.recentFiles.size(); ++k) {
menu.InsertMenu(k, MF_BYPOSITION | MF_ENABLED, 333 + k, prefs.recentFiles[k].c_str());
}
CMenu* file = GetMenu()->GetSubMenu(0);
file->InsertMenu(12, MF_BYPOSITION | MF_ENABLED | MF_POPUP, (UINT)menu.m_hMenu, "&Recent Files");
menu.Detach();
helpHome();
trackmem(true);
if (blitzIDE.m_lpCmdLine[0]) {
std::string t = std::string(blitzIDE.m_lpCmdLine);
if (t[0] == '\"') t = t.substr(1, t.size() - 2);
open(t);
}
else {
SetCurrentDirectory((prefs.homeDir + "/samples").c_str());
}
return 0;
}
void MainFrame::OnDropFiles(HDROP hDropInfo) {
TCHAR szFileName[MAX_PATH + 1] = {};
UINT nFiles = DragQueryFile(hDropInfo, 0xFFFFFFFF, szFileName, MAX_PATH);
for (int i = 0; i < nFiles; ++i)
{
DragQueryFile(hDropInfo, i, szFileName, MAX_PATH);
std::filesystem::path extension = std::filesystem::path(szFileName).extension();
if (extension == ".htm" || extension == ".html")
{
HtmlHelp* h = findHelp();
h->Navigate(szFileName);
} else if (extension == ".bb" || extension == ".txt")
open(szFileName);
else
ShellExecute(nullptr, "open", szFileName, "", "", SW_SHOW);
}
}
void MainFrame::OnDestroy() {
trackmem(false);
WINDOWPLACEMENT wp = { sizeof(wp) };
if (GetWindowPlacement(&wp)) {
prefs.win_rect = wp.rcNormalPosition;
if (wp.showCmd == SW_SHOWMAXIMIZED) {
prefs.win_maximized = true;
}
else {
prefs.win_maximized = false;
}
}
}
void MainFrame::setTitle(const std::string& s)
{
SetWindowText(("Blitz3D TSS - " + s).c_str());
return;
}
void MainFrame::OnClose() {
bool exit_flag = true;
for (int k = tabber.size() - 1; k >= 0; --k) {
exit_flag = close(k);
if (!exit_flag) break;
}
if (exit_flag) DestroyWindow();
}
BOOL MainFrame::OnEraseBkgnd(CDC* dc) {
return true;
}
void MainFrame::OnSize(UINT type, int sw, int sh) {
CFrameWnd::OnSize(type, sw, sh);
CRect r, t; GetClientRect(&r);
int x = r.left, y = r.top, w = r.Width(), h = r.Height();
if (!prefs.win_notoolbar) {
statusBar.GetWindowRect(&t); h -= t.Height();
toolBar.GetWindowRect(&t); y += t.Height(); h -= t.Height();
}
tabber.MoveWindow(x, y, w, h);
}
static const char* bbFilter =
"Blitz Basic files (.bb)|*.bb|"
"All files|*.*||";
Editor* MainFrame::getEditor() {
return getEditor(tabber.getCurrent());
}
Editor* MainFrame::getEditor(int n) {
std::map<CWnd*, Editor*>::iterator it = editors.find(tabber.getTabWnd(n));
return it == editors.end() ? 0 : it->second;
}
HtmlHelp* MainFrame::getHelp(int n) {
std::map<CWnd*, HtmlHelp*>::iterator it = helps.find(tabber.getTabWnd(n));
return it == helps.end() ? 0 : it->second;
}
HtmlHelp* MainFrame::getHelp() {
return getHelp(tabber.getCurrent());
}
HtmlHelp* MainFrame::findHelp() {
int n;
HtmlHelp* h;
for (n = 0; n < tabber.size(); ++n) {
if (h = getHelp(n)) break;
}
if (n == tabber.size()) {
h = new HtmlHelp(this);
h->Create(0, "Help", WS_CHILD | WS_BORDER, CRect(0, 0, 0, 0), &tabber, 1);
helps[h] = h;
tabber.insert(n, h, "Help");
}
tabber.setCurrent(n);
return h;
}
void MainFrame::cursorMoved(Editor* editor) {
if (editor != getEditor()) return;
int row, col;
editor->getCursor(&row, &col);
char mod = editor->getModified() ? '*' : ' ';
char str[64]; sprintf(str, "Row: %i Col: %i %c", row, col, mod);
statusBar.SetPaneText(1, str);
}
void MainFrame::currentSet(Tabber* tabber, int index) {
if (Editor* e = getEditor()) {
std::string t = e->getName();
if (!t.size()) t = "<untitled>";
setTitle(t);
cursorMoved(e);
}
else if (HtmlHelp* h = getHelp()) {
setTitle(h->getTitle());
statusBar.SetPaneText(1, "");
}
else {
setTitle("no file");
statusBar.SetPaneText(1, "");
}
}
void MainFrame::helpOpen(HtmlHelp* help, const std::string& file) {
open(file);
}
void MainFrame::helpTitleChange(HtmlHelp* help, const std::string& title) {
if (HtmlHelp* h = getHelp()) setTitle(h->getTitle());
}
void MainFrame::insertRecent(const std::string& file) {
//check recent files
if (CMenu* list = GetMenu()->GetSubMenu(0)->GetSubMenu(12)) {
std::vector<std::string>::iterator it;
std::vector<std::string>& f = prefs.recentFiles;
for (it = f.begin(); it != f.end(); ++it) {
if (tolower(*it) == tolower(file)) break;
}
if (it != f.end()) {
//move to top
std::string t = *it;
f.erase(it);
f.insert(f.begin(), t);
}
else {
//insert
if (f.size() == 10) {
f.pop_back();
list->RemoveMenu(9, MF_BYPOSITION);
}
f.insert(f.begin(), file);
list->InsertMenu(0, MF_BYPOSITION | MF_ENABLED, 333, file.c_str());
}
//renumber menu items
for (int k = 0; k < f.size(); ++k) {
list->ModifyMenu(k, MF_BYPOSITION | MF_ENABLED, 333 + k, f[k].c_str());
}
}
}
void MainFrame::newed(const std::string& t) {
CRect r(0, 0, 0, 0);
Editor* e = new Editor(this);
e->Create(0, "Editor", WS_CHILD, r, &tabber, 1);
e->setName(t);
editors[e] = e;
int n = tabber.size();
std::string s = t.size() ? getFile(t) : "<untitled>";
tabber.insert(n, e, s.c_str());
tabber.setCurrent(n);
}
bool MainFrame::open(const std::string& f) {
std::string file = f, filter = "*.bb";
int n = f.find("*.");
if (n != std::string::npos) {
file = f.substr(0, n);
filter = f.substr(n);
}
int attr = GetFileAttributes(file.c_str()); if (attr == -1) attr = 0;
if (!file.size() || (attr & FILE_ATTRIBUTE_DIRECTORY)) {
CFileDialog fd(true, "bb", filter.c_str(), OFN_NOCHANGEDIR | OFN_FILEMUSTEXIST, bbFilter);
char* i_dir = strdup(file.c_str());
fd.m_ofn.lpstrInitialDir = i_dir;
fd.m_ofn.lpstrTitle = "Open Blitz Basic File...";
int nn = fd.DoModal();
free(i_dir);
if (nn == IDCANCEL) return false;
file = fd.GetPathName();
}
else
{
char buff[MAX_PATH], * p;
if (GetFullPathName(file.c_str(), MAX_PATH, buff, &p)) file = buff;
else file = f;
}
//is file already open?
int k;
for (k = 0; k < tabber.size(); ++k) {
if (Editor* e = getEditor(k)) {
if (tolower(e->getName()) == tolower(file)) {
tabber.setCurrent(k);
return true;
}
}
}
//open new file
std::ifstream in(file.c_str());
if (!in.good()) {
std::string e = "Error reading file \"" + f + "\"";
AfxMessageBox(e.c_str(), MB_ICONWARNING);
return false;
}
newed(file);
tabber.UpdateWindow();
Editor* e = getEditor();
e->setText(in);
e->setName(file);
e->setModified(false);
insertRecent(file);
cursorMoved(e);
return true;
}
bool MainFrame::close(int n) {
if (Editor* e = getEditor(n)) {
if (e->getModified()) {
tabber.setCurrent(n);
std::string t = "File " + e->getName() + " has been modified!\nSave changes before closing?";
int rt = AfxMessageBox(t.c_str(), MB_YESNOCANCEL | MB_ICONWARNING);
if (rt == IDYES) return save(n);
if (rt == IDCANCEL) return false;
}
tabber.remove(n);
e->DestroyWindow();
editors.erase(e);
delete e;
}
else if (HtmlHelp* h = getHelp(n)) {
}
return true;
}
bool MainFrame::save(int n) {
Editor* e = getEditor(n);
if (!e) return true;
std::string t = e->getName();
if (!t.size()) {
tabber.setCurrent(n);
int df = OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_EXPLORER | OFN_OVERWRITEPROMPT;
CFileDialog fd(false, "bb", "*.bb", df, bbFilter);
fd.m_ofn.lpstrTitle = "Save Blitz Basic program as...";
if (fd.DoModal() == IDCANCEL) return false;
t = fd.GetPathName();
tabber.setTabText(n, getFile(t));
e->setName(t);
insertRecent(t);
}
//Do backups!
if (!prefs.noBackup) {
if (prefs.edit_backup) {
for (int k = prefs.edit_backup; k > 1; --k) {
CopyFile((t + "_bak" + itoa(k - 1)).c_str(), (t + "_bak" + itoa(k)).c_str(), false);
}
CopyFile(t.c_str(), (t + "_bak1").c_str(), false);
}
}
std::ofstream out(t.c_str(), std::ios_base::binary | std::ios_base::out | std::ios_base::trunc);
if (!out.good())
{
std::string e = "Error writing file \"" + t + "\"";
AfxMessageBox(e.c_str(), MB_ICONERROR);
return false;
}
e->getText(out);
out.close();
e->setModified(false);
cursorMoved(e);
return true;
}
void MainFrame::fileNew() {
newed("");
}
void MainFrame::fileOpen() {
open("");
}
void MainFrame::fileSave() {
save(tabber.getCurrent());
}
void MainFrame::fileSaveAs() {
if (Editor* e = getEditor()) {
std::string t = e->getName();
e->setName("");
if (!save(tabber.getCurrent())) e->setName(t);
currentSet(&tabber, tabber.getCurrent());
}
}
void MainFrame::fileSaveAll() {
for (int k = tabber.size() - 1; k >= 0; --k) {
if (!save(k)) return;
}
}
void MainFrame::filePrint() {
if (Editor* e = getEditor()) e->print();
}
void MainFrame::fileClose() {
close(tabber.getCurrent());
}
void MainFrame::fileCloseAll() {
for (int k = tabber.size() - 1; k >= 0; --k) {
if (!close(k)) return;
}
}
void MainFrame::fileExit() {
PostMessage(WM_CLOSE);
}
void MainFrame::fileRecent(UINT id) {
id -= 333;
if (id < 0 || id >= prefs.recentFiles.size()) return;
open(prefs.recentFiles[id]);
}
void MainFrame::editCut() {
if (Editor* e = getEditor()) e->cut();
}
void MainFrame::editCopy() {
if (Editor* e = getEditor()) e->copy();
}
void MainFrame::editPaste() {
if (Editor* e = getEditor()) e->paste();
}
void MainFrame::editSelectAll() {
if (Editor* e = getEditor()) e->selectAll();
}
void MainFrame::editFind() {
if (Editor* e = getEditor()) e->find();
}
void MainFrame::editFindNext() {
if (Editor* e = getEditor()) e->findNext(true);
}
void MainFrame::editReplace() {
if (Editor* e = getEditor()) e->replace();
}
static HANDLE startProc(const std::string& proc) {
HANDLE rd, wr;
SECURITY_ATTRIBUTES sa = { sizeof(sa),0,true };
if (CreatePipe(&rd, &wr, &sa, 0)) {
STARTUPINFO si = { sizeof(si) };
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdOutput = si.hStdError = wr;
PROCESS_INFORMATION pi = { 0 };
if (CreateProcess(0, (char*)proc.c_str(), 0, 0, true, DETACHED_PROCESS, 0, 0, &si, &pi)) {
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
CloseHandle(wr);
return rd;
}
CloseHandle(rd);
CloseHandle(wr);
}
return 0;
}
class PDialog : public CDialog {
public:
void OnOk() {}
void OnCancel() {}
};
void MainFrame::compile(const std::string& cmd) {
CDialog compiling;
compiling.Create(IDD_COMPILING);
CProgressCtrl* cp = (CProgressCtrl*)compiling.GetDlgItem(IDC_COMPILEPROGRESS);
cp->SetStep(20);
putenv("blitzide=1");
HANDLE rd = startProc(cmd);
if (!rd) {
putenv("blitzide");
compiling.DestroyWindow();
AfxMessageBox("Error launching compiler", MB_ICONWARNING | MB_OK);
return;
}
std::string line, err;
//OK....here we go!
for (;;) {
char buff;
unsigned long sz;
int n = ReadFile(rd, &buff, 1, &sz, 0);
if (n && !sz) break; //EOF!
if (!n && GetLastError() == ERROR_BROKEN_PIPE) break; //PROC END!
if (!n) { err = "Internal Error"; break; }
if (buff == '\r') continue;
if (buff != '\n') { line += buff; continue; }
if (!line.size()) continue;
if (line[0] == '\"') {
err = line;
int n = line.find("\"", 1);
if (n == std::string::npos) break;
if (++n == line.size() || line[n] != ':') break;
std::string file = line.substr(1, n - 2); line = line.substr(n + 1);
n = line.find(':'); if (!n || n == std::string::npos) break;
int row1 = atoi(line.substr(0, n)); line = line.substr(n + 1);
n = line.find(':'); if (!n || n == std::string::npos) break;
int col1 = atoi(line.substr(0, n)); line = line.substr(n + 1);
n = line.find(':'); if (!n || n == std::string::npos) break;
int row2 = atoi(line.substr(0, n)); line = line.substr(n + 1);
n = line.find(':'); if (!n || n == std::string::npos) break;
int col2 = atoi(line.substr(0, n)); line = line.substr(n + 1);
int pos = ((row1 - 1) << 16) | (col1 - 1);
if (!open(file)) return;
if (Editor* e = getEditor()) e->setCursor(pos);
err = line;
break;
}
else if (line.starts_with("[Message] ")) {
}
else if (line.find("...") != line.size() - 3) {
err = line; break;
}
if (line.find("Executing") == 0) {
//OK, we're running!
break;
}
cp->StepIt();
line = "";
}
compiling.DestroyWindow();
CloseHandle(rd);
putenv("blitzide");
if (!err.size()) return;
AfxMessageBox(err.c_str(), MB_ICONWARNING | MB_OK);
}
void MainFrame::build(bool exec, bool publish) {
Editor* e = getEditor();
if (!e) return;
std::string src_file = e->getName();
for (int k = tabber.size() - 1; k >= 0; --k) {
if (Editor* e = getEditor(k)) {
if (e->getModified() && e->getName().size()) {
if (!save(k)) return;
}
}
}
std::string opts = " ";
if (prefs.prg_preprocess) opts += "-p ";
if (prefs.prg_debug) opts += "-d ";
if (prefs.prg_nolaa) opts += "-nlaa ";
if (publish) {
std::string exe = src_file;
if (exe.size()) {
int n = exe.find('.');
if (n != std::string::npos) exe = exe.substr(0, n);
}
else {
exe = "untitled";
}
static const char* exeFilter = "Executable files (*.exe)|*.exe||";
int t = OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT;
CFileDialog fd(false, "exe", exe.c_str(), t, exeFilter);
fd.m_ofn.lpstrTitle = "Select executable filename";
fd.m_ofn.lpstrInitialDir = "./";
if (fd.DoModal() == IDCANCEL) return;
opts += "-o \"" + std::string(fd.GetPathName()) + "\" ";
}
else if (!exec) {
opts += "-c ";
}
std::string src = src_file;
//if the file doesnt exist, create a temporary file.
if (!src.size())
{
src = prefs.homeDir + "\\temp\\tmp.bb";
checkAndCreateDir(prefs.homeDir + "\\temp");
int om = std::ios_base::binary | std::ios_base::out | std::ios_base::trunc;
std::ofstream out(src.c_str(), om);
if (!out.good())
{
std::string e = "Error writing file \"" + src + "\"";
AfxMessageBox(e.c_str(), MB_ICONERROR);
return;
}
e->getText(out);
out.close();
e->setName(src);
}
else {
prefs.prg_lastbuild = e->getName();
}
compile(prefs.homeDir + "/bin/blitzcc -q " + opts + " \"" + src + "\" " + prefs.cmd_line);
if (!src_file.size()) e->setName("");
}
void MainFrame::programExecute() {
build(true, false);
}
void MainFrame::programReExecute() {
if (prefs.prg_lastbuild.size() && open(prefs.prg_lastbuild)) {
build(true, false);
}
}
void MainFrame::programCompile() {
build(false, false);
}
void MainFrame::programPublish() {
Editor* e = getEditor(); if (!e) return;
if (prefs.prg_debug) {
std::string t =
"You currently have the debugging feature enabled!\n\n"
"This will result in slower executables - continue anyway?";
if (MessageBox(t.c_str(), 0, MB_OKCANCEL) == IDCANCEL) return;
}
build(false, true);
}
struct CmdLineDialog : public CDialog {
CmdLineDialog() :CDialog(IDD_COMMANDLINE) {
}
BOOL OnInitDialog() {
CDialog::OnInitDialog();
SetDlgItemText(IDC_CMDLINE, prefs.cmd_line.c_str());
return TRUE;
}
void OnOK() {
CString c_str;
GetDlgItemText(IDC_CMDLINE, c_str);
prefs.cmd_line = c_str;
CDialog::OnOK();
}
};
void MainFrame::programCommandLine() {
CmdLineDialog d;
d.DoModal();
}
void MainFrame::programPreprocess() {
prefs.prg_preprocess = !prefs.prg_preprocess;
}
void MainFrame::programDebug() {
prefs.prg_debug = !prefs.prg_debug;
}
void MainFrame::programNoLAA() {
prefs.prg_nolaa = !prefs.prg_nolaa;
}
void MainFrame::helpHome() {
HtmlHelp* h = findHelp();
std::string t;
t = "index.html";
h->Navigate((prefs.homeDir + "/help/" + t).c_str());
}
void MainFrame::helpAutodoc() {
HtmlHelp* h = findHelp();
h->Navigate((prefs.homeDir + "/help/autodoc.html").c_str());
}
void MainFrame::helpBack() {
if (HtmlHelp* h = findHelp()) h->GoBack();
}
void MainFrame::helpForward() {
if (HtmlHelp* h = findHelp()) h->GoForward();
}
void MainFrame::helpAbout() {
aboutBlitz();
}
void MainFrame::ctrlTab() {
int n = tabber.getCurrent() + 1;
if (n >= tabber.size()) n -= tabber.size();
tabber.setCurrent(n);
}
void MainFrame::ctrlShiftTab() {
int n = tabber.getCurrent() - 1;
if (n < 0) n += tabber.size();
tabber.setCurrent(n);
}
void MainFrame::escape() {
if (!prefs.win_notoolbar) {
toolBar.ShowWindow(SW_HIDE);
statusBar.ShowWindow(SW_HIDE);
prefs.win_notoolbar = true;
}
else {
toolBar.ShowWindow(SW_SHOW);
statusBar.ShowWindow(SW_SHOW);
prefs.win_notoolbar = false;
}
RECT r; GetClientRect(&r);
int w = r.right - r.left, h = r.bottom - r.top;
int n = prefs.win_maximized ? SIZE_MAXIMIZED : SIZE_RESTORED;
PostMessage(WM_SIZE, n, (h << 16) | w);
}
void MainFrame::switchBackup() {
prefs.noBackup = !prefs.noBackup;
}
void MainFrame::updateCmdUIRange(CCmdUI* ui) {
int n = ui->m_nID - 333;
if (n >= 0 && n < prefs.recentFiles.size()) {
ui->Enable(true);
}
else {
ui->Enable(false);
}
}
void MainFrame::updateCmdUI(CCmdUI* ui) {
int k;
Editor* e = getEditor();
switch (ui->m_nID) {
case ID_NEW:case ID_OPEN:case ID_HOME:
ui->Enable(true);
break;
case ID_PROGRAM_PREPROCESSOR:
ui->SetCheck(prefs.prg_preprocess); ui->Enable(true);
break;
case ID_DEBUG:
ui->SetCheck(prefs.prg_debug); ui->Enable(true);
break;
case ID_NLAA:
ui->SetCheck(prefs.prg_nolaa); ui->Enable(true);
break;
case ID_CLOSE:case ID_PRINT:
ui->Enable(!!e);
break;
case ID_CLOSEALL:
for (k = 0; k < tabber.size() && !getEditor(k); ++k) {}
ui->Enable(k < tabber.size());
break;
case ID_CUT:case ID_COPY:
if (!!e) {
ui->Enable(e->canCutCopy());
}
else ui->Enable(false);
break;
case ID_PASTE:
if (!!e) {
ui->Enable(e->canPaste());
}
else ui->Enable(false);
break;
case ID_SELECTALL:case ID_QUICKHELP:
case ID_FIND:case ID_FINDNEXT:case ID_REPLACE:
case ID_EXECUTE:case ID_COMPILE:case ID_PUBLISH:
ui->Enable(!!e);
break;
case ID_REEXECUTE:
ui->Enable(prefs.prg_lastbuild.size());
break;
case ID_COMMANDLINE:
ui->Enable(true);
break;
case ID_SAVE:case ID_SAVEAS:
ui->Enable(!!e);
break;
case ID_SAVEALL:
for (k = 0; k < tabber.size() && !getEditor(k); ++k) {}
ui->Enable(k < tabber.size());
break;
case ID_BACK:case ID_FORWARD:
ui->Enable(getHelp() != 0);
break;
case ID_ESCAPE:
ui->SetCheck(!prefs.win_notoolbar);
break;
case ID_BACKUP:
ui->SetCheck(!prefs.noBackup);
break;
default:
ui->Enable(false);
}
}
static std::string commandURL(const std::string& t) {
static const char* dirs[] = {
"help\\commands\\2d_commands\\",
"help\\commands\\3d_commands\\",
0
};
const char** dir_p = dirs;
while (const char* dir = *dir_p++) {
WIN32_FIND_DATA fd;
std::string path = prefs.homeDir + "/" + dir + t + ".htm";
HANDLE h = FindFirstFile(path.c_str(), &fd);
if (h == INVALID_HANDLE_VALUE) continue;
FindClose(h);
return path;
}
return "";
}
void MainFrame::quick_Help() {
if (Editor* e = getEditor()) {
//look for keyword at cursor...
std::string t = e->getKeyword(); if (!t.size()) return;
if (t.substr(0, 6) == "Blitz_") t = t.substr(6, t.size());
statusBar.SetPaneText(0, quickHelp(t).c_str());
if (t != last_quick_help) {
last_quick_help = t;
return;
}
std::string url = commandURL(t);
if (!url.size()) {
std::string ex = "Unable to open help file for \"" + t + "\"";
AfxMessageBox(ex.c_str(), MB_ICONWARNING);
return;
}
if (HtmlHelp* h = findHelp()) {
h->Navigate(url.c_str(), 0, 0);
}
}
}
void MainFrame::OnActivate(UINT state, CWnd* other, BOOL min) {
CFrameWnd::OnActivate(state, other, min);
if (Editor* e = getEditor()) {
if (state != WA_ACTIVE && state != WA_CLICKACTIVE) return;
e->SetFocus();
}
}
void MainFrame::checkAndCreateDir(std::string dir)
{
CreateDirectory(dir.c_str(), 0);
}