summaryrefslogtreecommitdiff
path: root/src/common/console.c
diff options
context:
space:
mode:
authorshennetsind <ind@henn.et>2013-03-17 01:12:33 -0300
committershennetsind <ind@henn.et>2013-03-17 01:12:33 -0300
commit3b89a135dcde9779bd0537cd136a7c34cfadbe3f (patch)
treee963c1cf1f5e0168e7cd0b415d2e5963b229cb3d /src/common/console.c
parent5b1fee9ef54dbfc27fef5f6125a678fa88eba1be (diff)
downloadhercules-3b89a135dcde9779bd0537cd136a7c34cfadbe3f.tar.gz
hercules-3b89a135dcde9779bd0537cd136a7c34cfadbe3f.tar.bz2
hercules-3b89a135dcde9779bd0537cd136a7c34cfadbe3f.tar.xz
hercules-3b89a135dcde9779bd0537cd136a7c34cfadbe3f.zip
Re-Introducing Console Input
It's back. It's efficient. It's awesome. http://hercules.ws/board/topic/272-re-introducing-console-input/ Signed-off-by: shennetsind <ind@henn.et>
Diffstat (limited to 'src/common/console.c')
-rw-r--r--src/common/console.c186
1 files changed, 186 insertions, 0 deletions
diff --git a/src/common/console.c b/src/common/console.c
new file mode 100644
index 000000000..ee4570b2a
--- /dev/null
+++ b/src/common/console.c
@@ -0,0 +1,186 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
+
+#include "../common/showmsg.h"
+#include "../common/console.h"
+#include "../config/core.h"
+#include "core.h"
+
+#ifndef MINICORE
+ #include "../common/atomic.h"
+ #include "../common/spinlock.h"
+ #include "../common/thread.h"
+ #include "../common/mutex.h"
+ #include "../common/timer.h"
+ #include "../common/strlib.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifndef _WIN32
+ #include <unistd.h>
+#else
+ #include "../common/winapi.h" // Console close event handling
+#endif
+
+#ifdef CONSOLE_INPUT
+ #ifdef _WIN32
+ #include <conio.h> /* _kbhit() */
+ #endif
+#endif
+
+/*======================================
+ * CORE : Display title
+ *--------------------------------------*/
+void display_title(void) {
+ const char* svn = get_svn_revision();
+ const char* git = get_git_hash();
+
+ ShowMessage("\n");
+ ShowMessage(""CL_BG_RED" "CL_BT_WHITE" "CL_BG_RED""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_BG_RED" "CL_BT_WHITE" Hercules Development Team presents "CL_BG_RED""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_BG_RED" "CL_BT_WHITE" _ _ _ "CL_BG_RED""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_BG_RED" "CL_BT_WHITE" | | | | | | "CL_BG_RED""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_BG_RED" "CL_BT_WHITE" | |_| | ___ _ __ ___ _ _| | ___ ___ "CL_BG_RED""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_BG_RED" "CL_BT_WHITE" | _ |/ _ \\ '__/ __| | | | |/ _ \\/ __|"CL_BG_RED""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_BG_RED" "CL_BT_WHITE" | | | | __/ | | (__| |_| | | __/\\__ \\"CL_BG_RED""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_BG_RED" "CL_BT_WHITE" \\_| |_/\\___|_| \\___|\\__,_|_|\\___||___/"CL_BG_RED""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_BG_RED" "CL_BT_WHITE" "CL_BG_RED""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_BG_RED" "CL_BT_WHITE" http://hercules.ws/board/ "CL_BG_RED""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_BG_RED" "CL_BT_WHITE" "CL_BG_RED""CL_CLL""CL_NORMAL"\n");
+
+ if( git[0] != HERC_UNKNOWN_VER )
+ ShowInfo("Git Hash: '"CL_WHITE"%s"CL_RESET"'\n", git);
+ else if( svn[0] != HERC_UNKNOWN_VER )
+ ShowInfo("SVN Revision: '"CL_WHITE"%s"CL_RESET"'\n", svn);
+}
+#ifdef CONSOLE_INPUT
+#ifdef _WIN32
+int console_parse_key_pressed(void) {
+ return _kbhit();
+}
+#else /* _WIN32 */
+int console_parse_key_pressed(void) {
+ struct timeval tv;
+ fd_set fds;
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+ FD_ZERO(&fds);
+ FD_SET(STDIN_FILENO, &fds);
+
+ select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
+
+ return FD_ISSET(STDIN_FILENO, &fds);
+}
+#endif /* _WIN32 */
+
+void console_parse(char* line) {
+ int c, i = 0, len = MAX_CONSOLE_INPUT - 1;/* we leave room for the \0 :P */
+
+ while( (c = fgetc(stdin)) != EOF ) {
+ if( --len == 0 )
+ break;
+ if( (line[i++] = c) == '\n') {
+ line[i-1] = '\0';/* clear, we skip the new line */
+ break;/* new line~! we leave it for the next cycle */
+ }
+ }
+
+ line[i++] = '\0';
+}
+void *cThread_main(void *x) {
+
+ while( console->ptstate ) {/* loopx */
+ if( console->key_pressed() ) {
+ char input[MAX_CONSOLE_INPUT];
+
+ console->parse(input);
+ if( input[0] != '\0' ) {/* did we get something? */
+ EnterSpinLock(&console->ptlock);
+
+ if( cinput.count == CONSOLE_PARSE_SIZE ) {
+ LeaveSpinLock(&console->ptlock);
+ continue;/* drop */
+ }
+
+ safestrncpy(cinput.queue[cinput.count++],input,MAX_CONSOLE_INPUT);
+ LeaveSpinLock(&console->ptlock);
+ }
+ }
+ ramutex_lock( console->ptmutex );
+ racond_wait( console->ptcond, console->ptmutex, -1 );
+ ramutex_unlock( console->ptmutex );
+ }
+
+ return NULL;
+}
+int console_parse_timer(int tid, unsigned int tick, int id, intptr_t data) {
+ int i;
+ EnterSpinLock(&console->ptlock);
+ for(i = 0; i < cinput.count; i++) {
+ parse_console(cinput.queue[i]);
+ }
+ cinput.count = 0;
+ LeaveSpinLock(&console->ptlock);
+ racond_signal(console->ptcond);
+ return 0;
+}
+void console_parse_final(void) {
+ InterlockedDecrement(&console->ptstate);
+ racond_signal(console->ptcond);
+
+ /* wait for thread to close */
+ rathread_wait(console->pthread, NULL);
+
+ racond_destroy(console->ptcond);
+ ramutex_destroy(console->ptmutex);
+
+}
+void console_parse_init(void) {
+ cinput.count = 0;
+
+ console->ptstate = 1;
+
+ InitializeSpinLock(&console->ptlock);
+
+ console->ptmutex = ramutex_create();
+ console->ptcond = racond_create();
+
+ if( (console->pthread = rathread_create(console->pthread_main, NULL)) == NULL ){
+ ShowFatalError("console_parse_init: failed to spawn console_parse thread.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ add_timer_func_list(console->parse_timer, "console_parse_timer");
+ add_timer_interval(gettick() + 1000, console->parse_timer, 0, 0, 500);/* start listening in 1s; re-try every 0.5s */
+
+}
+#endif /* CONSOLE_INPUT */
+
+void console_init (void) {
+ console->display_title();
+#ifdef CONSOLE_INPUT
+ console->parse_init();
+#endif
+}
+void console_final(void) {
+#ifdef CONSOLE_INPUT
+ console->parse_final();
+#endif
+}
+void console_defaults(void) {
+ console = &console_s;
+ console->init = console_init;
+ console->final = console_final;
+ console->display_title = display_title;
+#ifdef CONSOLE_INPUT
+ console->parse_init = console_parse_init;
+ console->parse_final = console_parse_final;
+ console->parse_timer = console_parse_timer;
+ console->pthread_main = cThread_main;
+ console->parse = console_parse;
+ console->key_pressed = console_parse_key_pressed;
+#endif
+} \ No newline at end of file