/* * Dalos * Copyright (C) 2003-2005 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: Console.cc,v 1.7 2006-02-02 11:01:12 pixel Exp $ */ #include #include #include #include #include #include #include #include #include #include SDL_mutex * console_lock; SDL_sem * console_sem; Buffer console_buffer; SDL_mutex * key_vect_mutex; SDL_sem * key_vect_size; std::vector key_vect; String console_prompt = "> "; class ReadLineInternals : public Base { public: static int readline_thread(void * d) { char * line_read; String line, endline; bool runit; int pos; rl_getc_function = ReadLineInternals::rl_getc_func; rl_redisplay_function = ReadLineInternals::rl_redisplay_func; rl_prep_term_function = ReadLineInternals::rl_prep_term_func; rl_deprep_term_function = ReadLineInternals::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); CurrentConsole->add_line(console_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(console_lock); console_buffer << line; SDL_mutexV(console_lock); if (runit) { SDL_SemPost(console_sem); console_prompt = "> "; } else { console_prompt = "- "; } line = endline.trim(); } free(line_read); } return 0; } private: 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) { CurrentConsole->page_reset(); } static void rl_prep_term_func(int b) { } static void rl_deprep_term_func(void) { } }; void console::console_keyevent::down(SDL_keysym k) { if (CurrentConsole->GetVisible()) { SDL_mutexP(key_vect_mutex); switch (k.sym) { case SDLK_ESCAPE: CurrentConsole->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: CurrentConsole->page_up(); SDL_mutexV(key_vect_mutex); return; case SDLK_PAGEDOWN: CurrentConsole->page_down(); SDL_mutexV(key_vect_mutex); return; case SDLK_c: if (k.mod & KMOD_CTRL) { if (lua_started) do_lua_break = true; SDL_mutexV(key_vect_mutex); return; } default: if (k.unicode) { switch (k.unicode) { case 0xb4: key_vect.push_back('\''); break; case 0xa8: key_vect.push_back('"'); break; default: key_vect.push_back(k.unicode); } } else { SDL_mutexV(key_vect_mutex); if (old_handler) old_handler->down(k); return; } } // hack... if (lua_started) key_vect.pop_back(); SDL_mutexV(key_vect_mutex); if (!lua_started) SDL_SemPost(key_vect_size); } else { if (k.sym == SDLK_ESCAPE) { CurrentConsole->SetVisible(true); return; } if (old_handler) old_handler->down(k); } } void console::console_keyevent::up(SDL_keysym k) { if (old_handler) old_handler->up(k); } console::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); } console::~console() throw (GeneralException) { SDL_DestroyMutex(protect_add_line); } void console::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 console::page_reset() { page = 0; } void console::page_up() { page += nlines - 1; if (page > (lines.size() - nlines)) page = lines.size() - nlines; } void console::page_down() { page -= nlines - 1; if (page < 0) page = 0; } void console::draw() { int cursor_pos, start, line_length, line_pos, cur_page; mogltk::ColorP::Max.A = 180; std::vector::iterator i; // Background Shaper()->box(GetAX(), GetAY(), GetAX2(), GetAY2(), DODGERBLUE); 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 = 220; if (lua_started) { Shaper()->box(GetAX(), GetAY() + (nlines - 1) * 13, GetAX() + 6, GetAY() + nlines * 13, FORESTGREEN); } else { Shaper()->box(GetAX() + 6 * (cursor_pos + 2), GetAY() + (nlines - 1) * 13, GetAX() + 6 * (cursor_pos + 3) - 1, GetAY() + nlines * 13, FORESTGREEN); mogltk::ColorP::Max.A = 255; mogltk::FixedFont->putcursor(GetAX(), GetAY() + (nlines - 1) * 13); mogltk::FixedFont->printf("%s", console_prompt.to_charp()); mogltk::FixedFont->printf("%s", rl_line_buffer + start); } } bool console::process_event(int mx, int my, mogltk::event_t event) { return false; } void console::create_console_thread() { key_vect_mutex = SDL_CreateMutex(); key_vect_size = SDL_CreateSemaphore(0); SDL_CreateThread(ReadLineInternals::readline_thread, 0); } console * CurrentConsole;