diff options
author | pixel <pixel> | 2004-07-23 01:11:34 +0000 |
---|---|---|
committer | pixel <pixel> | 2004-07-23 01:11:34 +0000 |
commit | aa678bc560d5ac65f694ba485caae6e09531364f (patch) | |
tree | 614cd7ef37a9b31a467094dd2d37b82eeab0373d | |
parent | 6ea139d3259d0495d30a6a558876a431c77d3d30 (diff) |
Basic LUA in Dalos
-rw-r--r-- | Dalos/Dalos.cc | 441 |
1 files changed, 425 insertions, 16 deletions
diff --git a/Dalos/Dalos.cc b/Dalos/Dalos.cc index c9d8763..07bcbcd 100644 --- a/Dalos/Dalos.cc +++ b/Dalos/Dalos.cc @@ -1,24 +1,418 @@ +/* + * Dalos + * Copyright (C) 2004 Nicolas "Pixel" Noble + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: Dalos.cc,v 1.2 2004-07-23 01:11:34 pixel Exp $ */ + #include <SDL.h> +#include <SDL_thread.h> + +#include <readline/readline.h> +#include <readline/history.h> + +#include <vector> + #include <Main.h> +#include <Input.h> +#include <Buffer.h> +#include <BLua.h> +#include <LuaHandle.h> #include <engine.h> #include <glbase.h> #include <glshape.h> +#include <font.h> + +#ifdef __MINGW32__ +#define main SDL_main +#endif + +bool auto_exec = true; +bool started = false; +bool lua_break = false; + +String prompt = "> "; + +SDL_mutex * lua_command_lock; +SDL_sem * lua_command_sem; +Buffer lua_command; + +SDL_mutex * key_vect_mutex; +SDL_sem * key_vect_size; +std::vector<Uint16> key_vect; + +CODE_BEGINS +class console; + +console * Console; mogltk::widgets::Root * Root; -mogltk::widgets::Frame * Frame; +mogltk::widget * Frame; mogltk::widgets::Menu * MainMenu; -CODE_BEGINS + +static int lua_print(lua_State * _L) { + Lua * L = Lua::find(_L); + String t = L->tostring() + "\n"; + char * tc = t.strdup(); + + printm(M_STATUS, "%s", tc); + + free(tc); + + return 0; +} + +static void lua_hook(lua_State * _L, lua_Debug * ar) { + if (!started) + return; + Lua * L = Lua::find(_L); + + if (lua_break) { + L->error("Breaking"); + lua_break = false; + } +} + +static int rl_getc_func(FILE * d) { + int k; + SDL_SemWait(key_vect_size); + SDL_mutexP(key_vect_mutex); + k = key_vect[0]; + key_vect.erase(key_vect.begin()); + SDL_mutexV(key_vect_mutex); + return k; +} + +static void rl_redisplay_func(void) { + Application->Console->page_reset(); +} + +static void rl_prep_term_func(int b) { +} + +static void rl_deprep_term_func(void) { +} + +static int readline_thread(void * d) { + char * line_read; + String line, endline; + bool runit; + int pos; + + + rl_getc_function = rl_getc_func; + rl_redisplay_function = rl_redisplay_func; + rl_prep_term_function = rl_prep_term_func; + rl_deprep_term_function = rl_deprep_term_func; + rl_bind_key('\t', rl_insert); + + while (true) { + line_read = readline(""); + if (!line_read) + continue; + if (*line_read) + add_history(line_read); + Application->Console->add_line(prompt + line_read); + + line = line_read; + line = line.trim(); + endline = ""; + + /* Splitting the line between ;; */ + while (line.strlen()) { + runit = false; + + if ((pos = line.strstr(";;")) >= 0) { + endline = line.extract(pos + 2); + line = line.extract(0, pos); + runit = true; + } else { + endline = ""; + } + + if (line[line.strlen() - 1] == '\\') { + line[line.strlen() - 1] = ' '; + } else if (auto_exec) { + runit = true; + } + SDL_mutexP(lua_command_lock); + lua_command << line; + SDL_mutexV(lua_command_lock); + + if (runit) { + SDL_SemPost(lua_command_sem); + prompt = "> "; + } else { + prompt = "- "; + } + line = endline.trim(); + } + + free(line_read); + } + + return 0; +} + +void start_lua() { + Lua * L = new Lua(); + + L->open_base(); + L->open_math(); + L->open_string(); + L->open_table(); + + LuaInput::pushconstruct(L); + LuaOutput::pushconstruct(L); + LuaBuffer::pushconstruct(L); + + // CD_PUSHSTATICS(L); + // Luapsx::pushstatics(L); + + L->push("print"); + L->push(lua_print); + L->setvar(); + + L->sethook(lua_hook, LUA_MASKLINE, 0); + + lua_command_lock = SDL_CreateMutex(); + lua_command_sem = SDL_CreateSemaphore(0); + + SDL_CreateThread(LuaThread, L); +} + +static int LuaThread(void * d) { + Lua * L = (Lua *) d; + while (true) { + SDL_SemWait(lua_command_sem); + started = true; + SDL_mutexP(lua_command_lock); + try { + L->load(&lua_command); + } + catch (LuaException e) { + /* If there was an error, ignore it, and free the stack */ + while(L->gettop()) + L->pop(); + } + catch (GeneralException e) { + /* A more severe exception... */ + while(L->gettop()) + L->pop(); + printm(M_ERROR, "Aborted. LUA caused the following exception: %s\n", e.GetMsg()); + } + SDL_mutexV(lua_command_lock); + started = false; + } +} + +class console_keyevent : public mogltk::engine::keyevent { + public: + virtual void down(SDL_keysym k) { + if (Application->Console->GetVisible()) { + SDL_mutexP(key_vect_mutex); + switch (k.sym) { + case SDLK_ESCAPE: + Application->Console->SetVisible(false); + SDL_mutexV(key_vect_mutex); + return; + case SDLK_DELETE: + key_vect.push_back('D' - '@'); + break; + case SDLK_LEFT: + key_vect.push_back('B' - '@'); + break; + case SDLK_RIGHT: + key_vect.push_back('F' - '@'); + break; + case SDLK_UP: + key_vect.push_back('P' - '@'); + break; + case SDLK_DOWN: + key_vect.push_back('N' - '@'); + break; + case SDLK_HOME: + key_vect.push_back('A' - '@'); + break; + case SDLK_END: + key_vect.push_back('E' - '@'); + break; + case SDLK_PAGEUP: + Application->Console->page_up(); + SDL_mutexV(key_vect_mutex); + return; + case SDLK_PAGEDOWN: + Application->Console->page_down(); + SDL_mutexV(key_vect_mutex); + return; + case SDLK_c: + if (k.mod & KMOD_CTRL) { + if (started) + lua_break = true; + SDL_mutexV(key_vect_mutex); + return; + } + default: + if (k.unicode) { + key_vect.push_back(k.unicode); + } else { + SDL_mutexV(key_vect_mutex); + if (old_handler) + old_handler->down(k); + return; + } + } + SDL_mutexV(key_vect_mutex); + SDL_SemPost(key_vect_size); + } else { + if (k.sym == SDLK_ESCAPE) { + Application->Console->SetVisible(true); + return; + } + if (old_handler) + old_handler->down(k); + } + } + virtual void up(SDL_keysym k) { + if (old_handler) + old_handler->up(k); + } +}; + +class myprinter : public printer_t { + public: + myprinter() : lock(SDL_CreateMutex()) { } + virtual ~myprinter() { SDL_DestroyMutex(lock); } + virtual bool printm(int level, const char * m, va_list ap) { + static String heads[] = {"EE", "--", "WW", "II"}; + static char buffer[20480]; + + if (level >= M_INFO) + return true; + + SDL_mutexP(lock); + + vsprintf(buffer, m, ap); + if (level >= 0) + Application->Console->add_line("(" + heads[level] + ") " + buffer); + else + Application->Console->add_line(buffer); + + SDL_mutexV(lock); + + return true; + } + private: + SDL_mutex * lock; +}; + +class console : public mogltk::widget { + public: + console(mogltk::shape * sh, mogltk::widget * father, int y, int _nlines) : + widget(father, 0, y, father->GetW(), _nlines * 13, 0, "console", sh), nlines(_nlines), page(0), protect_add_line(SDL_CreateMutex()) { SetVisible(false); } + virtual ~console() { SDL_DestroyMutex(protect_add_line); } + void add_line(const String & s) { + SDL_mutexP(protect_add_line); + lines.insert(lines.begin(), 1, s); + while (lines.size() >= 1024) { + lines.pop_back(); + } + SDL_mutexV(protect_add_line); + } + void page_reset() { + page = 0; + } + void page_up() { + page += nlines; + if (page > (lines.size() - nlines)) + page = lines.size() - nlines; + } + void page_down() { + page -= nlines; + if (page < 0) + page = 0; + } + protected: + virtual void draw() { + int cursor_pos, start, line_length, line_pos, cur_page; + + mogltk::ColorP::Max.A = 120; + std::vector<String>::iterator i; + + // Background + Shaper()->box(GetAX(), GetAY(), GetAX2(), GetAY2(), BLUE); + Shaper()->obox(GetAX(), GetAY(), GetAX2(), GetAY2(), BLUE); + + mogltk::ColorP::Max.A = 255; + mogltk::FixedFont->setcolor(WHITE); + + // Lines + SDL_mutexP(protect_add_line); + i = lines.begin(); + for (cur_page = page; cur_page && (i != lines.end()); cur_page--, i++); + + for (line_pos = nlines - 2; (line_pos >= 0) && (i != lines.end()); line_pos--, i++) { + const char * line; + mogltk::FixedFont->putcursor(GetAX(), GetAY() + line_pos * 13); + line = i->to_charp(); + mogltk::FixedFont->printf("%s", line); + } + SDL_mutexV(protect_add_line); + + // Cursor + cursor_pos = rl_point; + start = 0; + + line_length = strlen(rl_line_buffer); + +// while ((((cursor_pos + 2) * 6) >= GetW() || (((line_length - start + 2) * 6) >= GetW())) && (cursor_pos >= 16)) { + while (((cursor_pos + 2) * 6) >= GetW()) { + cursor_pos -= 16; + start += 16; + } + + mogltk::ColorP::Max.A = 200; + Shaper()->box(GetAX() + 6 * (cursor_pos + 2), GetAY() + (nlines - 1) * 13, GetAX() + 6 * (cursor_pos + 3) - 1, GetAY() + nlines * 13, GREEN); + + mogltk::ColorP::Max.A = 255; + mogltk::FixedFont->putcursor(GetAX(), GetAY() + (nlines - 1) * 13); + mogltk::FixedFont->printf(prompt); + mogltk::FixedFont->printf("%s", rl_line_buffer + start); + } + virtual bool process_event(int mx, int my, mogltk::event_t event) { + } + private: + int nlines, page; + std::vector<String> lines; + SDL_mutex * protect_add_line; +}; class frame : public mogltk::widget { public: frame(mogltk::shape * sh, mogltk::widget * father) : widget(father, 2, 2, father->GetW() - 4, father->GetH() - 4, 0, "MyFrame", sh) { } - protected: + protected: virtual void draw() { } virtual bool process_event(int mx, int my, mogltk::event_t event) { + mx -= GetAX(); + my -= GetAY(); return false; } }; @@ -26,7 +420,7 @@ class frame : public mogltk::widget { class timer : public mogltk::widget { public: timer() : - widget(Root, 0, 0, 0, 0, 0, "Timer", 0), tick(0) + widget(Application->Root, 0, 0, 0, 0, 0, "Timer", 0), tick(0) { set_timed_event(100); } protected: virtual bool process_event(int, int, mogltk::event_t event) { @@ -35,18 +429,19 @@ class timer : public mogltk::widget { tick = (tick + 1) % 4; switch (tick) { case 0: - MainMenu->SetCaption(0, "/"); + Application->MainMenu->SetCaption(0, "/"); break; case 1: - MainMenu->SetCaption(0, "-"); + Application->MainMenu->SetCaption(0, "-"); break; case 2: - MainMenu->SetCaption(0, "\\"); + Application->MainMenu->SetCaption(0, "\\"); break; case 3: - MainMenu->SetCaption(0, "I"); + Application->MainMenu->SetCaption(0, "I"); break; } + Application->MainMenu->SetCaption(3, String("FPS: ") + mogltk::engine::FPS()); return true; } return false; @@ -79,35 +474,49 @@ class about : public mogltk::widgets::action { } about_dialog; virtual int startup() throw (GeneralException) { + verbosity = M_INFO; + new Archive(argv[0], ARCHIVE_EXECUTABLE); + mogltk::widgets::ContextMenu * c; mogltk::base * gl = new mogltk::glbase(); mogltk::shape * sh = new mogltk::glshape(); + key_vect_mutex = SDL_CreateMutex(); + key_vect_size = SDL_CreateSemaphore(0); + + SDL_EnableKeyRepeat(250, 40); + mogltk::engine::setcursorvisible(true); mogltk::engine::setappactive(true); Root = new mogltk::widgets::Root(sh); MainMenu = new mogltk::widgets::Menu(sh, Root); - Frame = new mogltk::widgets::Frame(sh, Root, 0, MainMenu->GetH(), Root->GetW() - 1, Root->GetH() - MainMenu->GetH() - 1); - new frame(sh, Frame); + Frame = new frame(sh, new mogltk::widgets::Frame(sh, Root, 0, MainMenu->GetH(), Root->GetW() - 1, Root->GetH() - MainMenu->GetH() - 1)); + Console = new console(sh, Frame, 0, 8); + Console->move(0, Frame->GetH() - Console->GetH()); + Console->add_line("Dalos v0.1 - LUA console"); + + start_lua(); + + printer = new myprinter(); + SDL_CreateThread(readline_thread, 0); MainMenu->addnode("/", 0); c = MainMenu->createsub("File"); - c->addnode("Load", 0); - c->addnode("Save", 0); - c->addline(); c->addnode("Quit", &action_quit); - c = MainMenu->createsub("Execution"); - c->addnode("Run", 0); - c = MainMenu->createsub("Help"); c->addnode("About", &about_dialog); + + MainMenu->addnode("FPS:", 0); new timer(); + new console_keyevent; Root->mainloop(); + + // Should cleanup here... return 0; } |