bsnes/phoenix/gtk/widget/console.cpp

187 lines
6.3 KiB
C++
Raw Normal View History

namespace phoenix {
static bool Console_keyPress(GtkWidget* widget, GdkEventKey* event, Console* self) {
return self->p.keyPress(event->keyval, event->state);
}
void pConsole::print(string text) {
//insert text before prompt and command
GtkTextIter iter;
gtk_text_buffer_get_iter_at_line_offset(textBuffer, &iter, gtk_text_buffer_get_line_count(textBuffer), 0);
gtk_text_buffer_insert(textBuffer, &iter, text, -1);
seekToEnd();
}
void pConsole::reset() {
//flush history and redraw prompt
gtk_text_buffer_set_text(textBuffer, console.prompt(), -1);
seekToEnd();
}
Update to v094r08 release. byuu says: Lots of changes this time around. FreeBSD stability and compilation is still a work in progress. FreeBSD 10 + Clang 3.3 = 108fps FreeBSD 10 + GCC 4.7 = 130fps Errata 1: I've been fighting that god-damned endian.h header for the past nine WIPs now. The above WIP isn't building now because FreeBSD isn't including headers before using certain types, and you end up with a trillion error messages. So just delete all the endian.h includes from nall/intrinsics.hpp to build. Errata 2: I was trying to match g++ and g++47, so I used $(findstring g++,$(compiler)), which ends up also matching clang++. Oops. Easy fix, put Clang first and then else if g++ next. Not ideal, but oh well. All it's doing for now is declaring -fwrapv twice, so you don't have to fix it just yet. Probably just going to alias g++="g++47" and do exact matching instead. Errata 3: both OpenGL::term and VideoGLX::term are causing a core dump on BSD. No idea why. The resources are initialized and valid, but releasing them crashes the application. Changelog: - nall/Makefile is more flexible with overriding $(compiler), so you can build with GCC or Clang on BSD (defaults to GCC now) - PLATFORM_X was renamed to PLATFORM_XORG, and it's also declared with PLATFORM_LINUX or PLATFORM_BSD - PLATFORM_XORG probably isn't the best name ... still thinking about what best to call LINUX|BSD|SOLARIS or ^(WINDOWS|MACOSX) - fixed a few legitimate Clang warning messages in nall - Compiler::VisualCPP is ugly as hell, renamed to Compiler::CL - nall/platform includes nall/intrinsics first. Trying to move away from testing for _WIN32, etc directly in all files. Work in progress. - nall turns off Clang warnings that I won't "fix", because they aren't broken. It's much less noisy to compile with warnings on now. - phoenix gains the ability to set background and foreground colors on various text container widgets (GTK only for now.) - rewrote a lot of the MSU1 code to try and simplify it. Really hope I didn't break anything ... I don't have any MSU1 test ROMs handy - SNES coprocessor audio is now mixed as sclamp<16>(system_sample + coprocessor_sample) instead of sclamp<16>((sys + cop) / 2) - allows for greater chance of aliasing (still low, SNES audio is quiet), but doesn't cut base system volume in half anymore - fixed Super Scope and Justifier cursor colors - use input.xlib instead of input.x ... allows Xlib input driver to be visible on Linux and BSD once again - make install and make uninstall must be run as root again; no longer using install but cp instead for BSD compatibility - killed $(DESTDIR) ... use make prefix=$DESTDIR$prefix instead - you can now set text/background colors for the loki console via (eg): - settings.terminal.background-color 0x000000 - settings.terminal.foreground-color 0xffffff
2014-02-24 09:39:09 +00:00
void pConsole::setBackgroundColor(Color color) {
GdkColor gdkColor = CreateColor(color.red, color.green, color.blue);
gtk_widget_modify_base(subWidget, GTK_STATE_NORMAL, &gdkColor);
}
void pConsole::setForegroundColor(Color color) {
GdkColor gdkColor = CreateColor(color.red, color.green, color.blue);
gtk_widget_modify_text(subWidget, GTK_STATE_NORMAL, &gdkColor);
}
void pConsole::setPrompt(string prompt) {
//erase previous prompt and replace it with new prompt
GtkTextIter lhs, rhs;
gtk_text_buffer_get_iter_at_line_offset(textBuffer, &lhs, gtk_text_buffer_get_line_count(textBuffer), 0);
gtk_text_buffer_get_iter_at_line_offset(textBuffer, &rhs, gtk_text_buffer_get_line_count(textBuffer), previousPrompt.size());
gtk_text_buffer_delete(textBuffer, &lhs, &rhs);
gtk_text_buffer_get_iter_at_line_offset(textBuffer, &lhs, gtk_text_buffer_get_line_count(textBuffer), 0);
gtk_text_buffer_insert(textBuffer, &lhs, previousPrompt = prompt, -1);
seekToEnd();
}
void pConsole::constructor() {
gtkWidget = gtk_scrolled_window_new(0, 0);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(gtkWidget), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(gtkWidget), GTK_SHADOW_ETCHED_IN);
subWidget = gtk_text_view_new();
gtk_text_view_set_editable(GTK_TEXT_VIEW(subWidget), false);
gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(subWidget), GTK_WRAP_NONE);
gtk_container_add(GTK_CONTAINER(gtkWidget), subWidget);
textBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(subWidget));
g_signal_connect(G_OBJECT(subWidget), "key-press-event", G_CALLBACK(Console_keyPress), (gpointer)&console);
gtk_widget_show(subWidget);
}
void pConsole::destructor() {
gtk_widget_destroy(subWidget);
gtk_widget_destroy(gtkWidget);
}
void pConsole::orphan() {
destructor();
constructor();
}
bool pConsole::keyPress(unsigned scancode, unsigned mask) {
if(mask & (GDK_CONTROL_MASK | GDK_MOD1_MASK | GDK_SUPER_MASK)) return false; //allow actions such as Ctrl+C (copy)
GtkTextMark* mark = gtk_text_buffer_get_mark(textBuffer, "insert");
GtkTextIter start, cursor, end;
gtk_text_buffer_get_iter_at_line_offset(textBuffer, &start, gtk_text_buffer_get_line_count(textBuffer), console.prompt().size());
gtk_text_buffer_get_iter_at_mark(textBuffer, &cursor, mark);
gtk_text_buffer_get_end_iter(textBuffer, &end);
if(scancode == GDK_KEY_Return || scancode == GDK_KEY_KP_Enter) {
char* temp = gtk_text_buffer_get_text(textBuffer, &start, &end, true);
string s = temp;
g_free(temp);
gtk_text_buffer_insert(textBuffer, &end, string{"\n", console.prompt()}, -1);
if(console.onActivate) console.onActivate(s);
if(s) history.prepend(s);
if(history.size() > 128) history.removeLast();
historyOffset = 0;
seekToEnd();
return true;
}
if(scancode == GDK_KEY_Up) {
gtk_text_buffer_delete(textBuffer, &start, &end);
gtk_text_buffer_get_end_iter(textBuffer, &end);
if(historyOffset < history.size()) {
gtk_text_buffer_insert(textBuffer, &end, history[historyOffset++], -1);
}
seekToEnd();
return true;
}
if(scancode == GDK_KEY_Down) {
gtk_text_buffer_delete(textBuffer, &start, &end);
gtk_text_buffer_get_end_iter(textBuffer, &end);
if(historyOffset > 0) {
gtk_text_buffer_insert(textBuffer, &end, history[--historyOffset], -1);
}
seekToEnd();
return true;
}
if(scancode == GDK_KEY_Left) {
if(gtk_text_iter_get_offset(&cursor) <= gtk_text_iter_get_offset(&start)) {
gtk_text_buffer_place_cursor(textBuffer, &start);
} else {
gtk_text_iter_set_offset(&cursor, gtk_text_iter_get_offset(&cursor) - 1);
gtk_text_buffer_place_cursor(textBuffer, &cursor);
}
seekToMark();
return true;
}
if(scancode == GDK_KEY_Right) {
if(gtk_text_iter_get_offset(&cursor) < gtk_text_iter_get_offset(&start)) {
gtk_text_buffer_place_cursor(textBuffer, &end);
} else if(gtk_text_iter_get_offset(&cursor) < gtk_text_iter_get_offset(&end)) {
gtk_text_iter_set_offset(&cursor, gtk_text_iter_get_offset(&cursor) + 1);
gtk_text_buffer_place_cursor(textBuffer, &cursor);
}
seekToMark();
return true;
}
if(scancode == GDK_KEY_Home) {
gtk_text_buffer_place_cursor(textBuffer, &start);
seekToMark();
return true;
}
if(scancode == GDK_KEY_End) {
gtk_text_buffer_place_cursor(textBuffer, &end);
seekToMark();
return true;
}
if(scancode == GDK_KEY_BackSpace) {
if(gtk_text_iter_get_offset(&cursor) <= gtk_text_iter_get_offset(&start)) return true;
GtkTextIter lhs = cursor;
gtk_text_iter_set_offset(&lhs, gtk_text_iter_get_offset(&cursor) - 1);
gtk_text_buffer_delete(textBuffer, &lhs, &cursor);
seekToMark();
return true;
}
if(scancode == GDK_KEY_Delete) {
if(gtk_text_iter_get_offset(&cursor) < gtk_text_iter_get_offset(&start)) return true;
if(gtk_text_iter_get_offset(&cursor) == gtk_text_iter_get_offset(&end)) return true;
GtkTextIter rhs = cursor;
gtk_text_iter_set_offset(&rhs, gtk_text_iter_get_offset(&cursor) + 1);
gtk_text_buffer_delete(textBuffer, &cursor, &rhs);
seekToMark();
return true;
}
if(scancode >= 0x20 && scancode <= 0x7e) {
if(gtk_text_iter_get_offset(&cursor) < gtk_text_iter_get_offset(&start)) return true;
gtk_text_buffer_insert(textBuffer, &cursor, string{(char)scancode}, -1);
seekToMark();
return true;
}
return false;
}
void pConsole::seekToEnd() {
GtkTextIter iter;
gtk_text_buffer_get_end_iter(textBuffer, &iter);
gtk_text_buffer_place_cursor(textBuffer, &iter);
seekToMark();
}
void pConsole::seekToMark() {
GtkTextMark* mark = gtk_text_buffer_get_mark(textBuffer, "insert");
gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(subWidget), mark);
}
}