void TextConsoleViewer::view() { #ifdef _WIN32 int topline, leftpos; leftpos = topline = 0; INPUT_RECORD ir; HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE); HANDLE hConI = CreateFile("CONIN$", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if (hConI == INVALID_HANDLE_VALUE) return; SetConsoleMode(hConI, ENABLE_MOUSE_INPUT|ENABLE_WINDOW_INPUT); CONSOLE_SCREEN_BUFFER_INFO csbi; hCon = CreateConsoleScreenBuffer(GENERIC_WRITE|GENERIC_READ, 0, 0, CONSOLE_TEXTMODE_BUFFER, 0); SetConsoleActiveScreenBuffer(hCon); GetConsoleScreenBufferInfo(hCon, &csbi); CONSOLE_CURSOR_INFO cci; cci.dwSize = 100; cci.bVisible = FALSE; SetConsoleCursorInfo(hCon, &cci); CHAR_INFO *buffer = new CHAR_INFO[csbi.dwSize.X * csbi.dwSize.Y]; bool unc_fault = false; do { int lline = csbi.dwSize.Y; if (topline+lline > textLinesStore->getLineCount()) lline = textLinesStore->getLineCount()-topline; baseEditor->visibleTextEvent(topline, lline); for(int i = topline; i < topline + csbi.dwSize.Y; i++) { int Y = i-topline; int li; for(li = 0; li < csbi.dwSize.X; li++) { buffer[Y*csbi.dwSize.X + li].Char.UnicodeChar = ' '; buffer[Y*csbi.dwSize.X + li].Attributes = background; }; if (i >= textLinesStore->getLineCount()) continue; DString iLine = textLinesStore->getLine(i); for(li = 0; li < csbi.dwSize.X; li++) { if (leftpos+li >= iLine.length()) break; buffer[Y*csbi.dwSize.X + li].Char.UnicodeChar = iLine[leftpos+li]; if (unc_fault) buffer[Y*csbi.dwSize.X + li].Char.AsciiChar = Encodings::toChar(encoding, iLine[leftpos+li]); }; for(LineRegion *l1 = baseEditor->getLineRegions(i); l1 != null; l1 = l1->next) { if (l1->special || l1->rdef == null) continue; int end = l1->end; if (end == -1) end = iLine.length(); int X = l1->start - leftpos; int len = end - l1->start; if (X < 0) { len += X; X = 0; }; if (len < 0 || X >= csbi.dwSize.X) continue; if (len+X > csbi.dwSize.X) len = csbi.dwSize.X-X; WORD color = (WORD)(l1->styled()->fore + (l1->styled()->back<<4)); if (!l1->styled()->bfore) color = (color&0xF0) + (background&0xF); if (!l1->styled()->bback) color = (color&0xF) + (background&0xF0); for(int li = 0; li < len; li++) buffer[Y*csbi.dwSize.X + X + li].Attributes = color; }; }; COORD coor; coor.X = coor.Y = 0; SMALL_RECT sr; sr.Left = 0; sr.Right = csbi.dwSize.X-1; sr.Top = 0; sr.Bottom = csbi.dwSize.Y-1; if (!unc_fault && !WriteConsoleOutputW(hCon, buffer, csbi.dwSize, coor, &sr)) { unc_fault = true; continue; }; if (unc_fault) WriteConsoleOutputA(hCon, buffer, csbi.dwSize, coor, &sr); // managing the keyboard do { DWORD tmp; ReadConsoleInput(hConI, &ir, 1, &tmp); if (ir.EventType == WINDOW_BUFFER_SIZE_EVENT) { GetConsoleScreenBufferInfo(hCon, &csbi); delete[] buffer; buffer = new CHAR_INFO[csbi.dwSize.X * csbi.dwSize.Y]; break; }; if (ir.EventType == MOUSE_EVENT && ir.Event.MouseEvent.dwEventFlags == 0x4) { switch(ir.Event.MouseEvent.dwButtonState) { case 0x780000: topline-=csbi.dwSize.Y; if (topline < 0) topline = 0; break; case 0xFF880000: topline += csbi.dwSize.Y; if (topline > textLinesStore->getLineCount() - csbi.dwSize.Y) topline = textLinesStore->getLineCount() - csbi.dwSize.Y; if (topline < 0) topline = 0; break; }; break; }; if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown) { // moving view position switch(ir.Event.KeyEvent.wVirtualKeyCode) { case VK_UP: if (topline) topline--; break; case VK_DOWN: if (topline+csbi.dwSize.Y < textLinesStore->getLineCount()) topline++; break; case VK_LEFT: leftpos--; if (ir.Event.KeyEvent.dwControlKeyState & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED)) leftpos -= 15; if (leftpos < 0) leftpos = 0; break; case VK_RIGHT: leftpos++; if (ir.Event.KeyEvent.dwControlKeyState & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED)) leftpos += 15; break; case VK_PRIOR: topline-=csbi.dwSize.Y; if (topline < 0) topline = 0; break; case VK_NEXT: case VK_SPACE: topline += csbi.dwSize.Y; if (topline > textLinesStore->getLineCount() - csbi.dwSize.Y) topline = textLinesStore->getLineCount() - csbi.dwSize.Y; if (topline < 0) topline = 0; break; case VK_HOME: leftpos = topline = 0; break; case VK_END: topline = textLinesStore->getLineCount()-csbi.dwSize.Y; if (topline < 0) topline = 0; leftpos = 0; break; }; break; }; } while(true); } while(ir.Event.KeyEvent.wVirtualKeyCode != VK_ESCAPE); delete[] buffer; SetConsoleActiveScreenBuffer(GetStdHandle(STD_OUTPUT_HANDLE)); CloseHandle(hCon); #else printf("unix edition doesn't support interactive text viewing\n\n"); for(int i = 0; i < textLinesStore->getLineCount(); i++) { DString line = textLinesStore->getLine(i); printf("%s\n", line.getChars()); }; #endif };
/* ================== CON_Input ================== */ char *CON_Input( void ) { INPUT_RECORD buff[ MAX_EDIT_LINE ]; DWORD count = 0, events = 0; WORD key = 0; int i; int newlinepos = -1; if ( !GetNumberOfConsoleInputEvents( qconsole_hin, &events ) ) { return NULL; } if ( events < 1 ) { return NULL; } // if we have overflowed, start dropping oldest input events if ( events >= MAX_EDIT_LINE ) { ReadConsoleInput( qconsole_hin, buff, 1, &events ); return NULL; } if ( !ReadConsoleInput( qconsole_hin, buff, events, &count ) ) { return NULL; } FlushConsoleInputBuffer( qconsole_hin ); for ( i = 0; i < count; i++ ) { if ( buff[ i ].EventType != KEY_EVENT ) { continue; } if ( !buff[ i ].Event.KeyEvent.bKeyDown ) { continue; } key = buff[ i ].Event.KeyEvent.wVirtualKeyCode; if ( key == VK_RETURN ) { newlinepos = i; break; } else if ( key == VK_UP ) { Q_strncpyz( qconsole_line, Hist_Prev(), sizeof( qconsole_line ) ); qconsole_linelen = strlen( qconsole_line ); break; } else if ( key == VK_DOWN ) { const char *history = Hist_Next(); if ( history ) { Q_strncpyz( qconsole_line, history, sizeof( qconsole_line ) ); qconsole_linelen = strlen( qconsole_line ); } else if ( qconsole_linelen ) { Hist_Add( qconsole_line ); qconsole_line[ 0 ] = '\0'; qconsole_linelen = 0; } break; } else if ( key == VK_TAB ) { field_t f; Q_strncpyz( f.buffer, qconsole_line, sizeof( f.buffer ) ); Field_AutoComplete( &f, "]" ); Q_strncpyz( qconsole_line, f.buffer, sizeof( qconsole_line ) ); qconsole_linelen = strlen( qconsole_line ); break; } if ( qconsole_linelen < sizeof( qconsole_line ) - 1 ) { char c = buff[ i ].Event.KeyEvent.uChar.AsciiChar; if ( key == VK_BACK ) { int pos = ( qconsole_linelen > 0 ) ? qconsole_linelen - 1 : 0; qconsole_line[ pos ] = '\0'; qconsole_linelen = pos; } else if ( c ) { qconsole_line[ qconsole_linelen++ ] = c; qconsole_line[ qconsole_linelen ] = '\0'; } } } CON_Show(); if ( newlinepos < 0 ) { return NULL; } if ( !qconsole_linelen ) { Com_Printf( "\n" ); return NULL; } Hist_Add( qconsole_line ); Com_Printf( "]%s\n", qconsole_line ); qconsole_linelen = 0; return qconsole_line; }
vlc_bool_t ReadWin32( intf_thread_t *p_intf, char *p_buffer, int *pi_size ) { INPUT_RECORD input_record; DWORD i_dw; /* On Win32, select() only works on socket descriptors */ while( WaitForSingleObject( p_intf->p_sys->hConsoleIn, INTF_IDLE_SLEEP/1000 ) == WAIT_OBJECT_0 ) { while( !p_intf->b_die && *pi_size < MAX_LINE_LENGTH && ReadConsoleInput( p_intf->p_sys->hConsoleIn, &input_record, 1, &i_dw ) ) { if( input_record.EventType != KEY_EVENT || !input_record.Event.KeyEvent.bKeyDown || input_record.Event.KeyEvent.wVirtualKeyCode == VK_SHIFT || input_record.Event.KeyEvent.wVirtualKeyCode == VK_CONTROL|| input_record.Event.KeyEvent.wVirtualKeyCode == VK_MENU || input_record.Event.KeyEvent.wVirtualKeyCode == VK_CAPITAL ) { /* nothing interesting */ continue; } p_buffer[ *pi_size ] = input_record.Event.KeyEvent.uChar.AsciiChar; /* Echo out the command */ putc( p_buffer[ *pi_size ], stdout ); /* Handle special keys */ if( p_buffer[ *pi_size ] == '\r' || p_buffer[ *pi_size ] == '\n' ) { putc( '\n', stdout ); break; } switch( p_buffer[ *pi_size ] ) { case '\b': if( *pi_size ) { *pi_size -= 2; putc( ' ', stdout ); putc( '\b', stdout ); } break; case '\r': (*pi_size) --; break; } (*pi_size)++; } if( *pi_size == MAX_LINE_LENGTH || p_buffer[ *pi_size ] == '\r' || p_buffer[ *pi_size ] == '\n' ) { p_buffer[ *pi_size ] = 0; return VLC_TRUE; } } return VLC_FALSE; }
static int _process_mouse_event(void) { static const DWORD button_mask[] = {1, 4, 2}; short action, shift_flags = 0; int i; save_press = 0; SP->key_code = TRUE; memset(&pdc_mouse_status, 0, sizeof(MOUSE_STATUS)); /* Handle scroll wheel */ if (MEV.dwEventFlags == 4) { pdc_mouse_status.changes = (MEV.dwButtonState & 0xFF000000) ? PDC_MOUSE_WHEEL_DOWN : PDC_MOUSE_WHEEL_UP; pdc_mouse_status.x = -1; pdc_mouse_status.y = -1; memset(&old_mouse_status, 0, sizeof(old_mouse_status)); return KEY_MOUSE; } if (MEV.dwEventFlags == 8) { pdc_mouse_status.changes = (MEV.dwButtonState & 0xFF000000) ? PDC_MOUSE_WHEEL_RIGHT : PDC_MOUSE_WHEEL_LEFT; pdc_mouse_status.x = -1; pdc_mouse_status.y = -1; memset(&old_mouse_status, 0, sizeof(old_mouse_status)); return KEY_MOUSE; } action = (MEV.dwEventFlags == 2) ? BUTTON_DOUBLE_CLICKED : ((MEV.dwEventFlags == 1) ? BUTTON_MOVED : BUTTON_PRESSED); for (i = 0; i < 3; i++) pdc_mouse_status.button[i] = (MEV.dwButtonState & button_mask[i]) ? action : 0; if (action == BUTTON_PRESSED && MEV.dwButtonState & 7 && SP->mouse_wait) { /* Check for a click -- a PRESS followed immediately by a release */ if (!event_count) { napms(SP->mouse_wait); GetNumberOfConsoleInputEvents(pdc_con_in, &event_count); } if (event_count) { INPUT_RECORD ip; DWORD count; bool have_click = FALSE; PeekConsoleInput(pdc_con_in, &ip, 1, &count); for (i = 0; i < 3; i++) { if (pdc_mouse_status.button[i] == BUTTON_PRESSED && !(ip.Event.MouseEvent.dwButtonState & button_mask[i])) { pdc_mouse_status.button[i] = BUTTON_CLICKED; have_click = TRUE; } } /* If a click was found, throw out the event */ if (have_click) ReadConsoleInput(pdc_con_in, &ip, 1, &count); } } pdc_mouse_status.x = MEV.dwMousePosition.X; pdc_mouse_status.y = MEV.dwMousePosition.Y; pdc_mouse_status.changes = 0; for (i = 0; i < 3; i++) { if (old_mouse_status.button[i] != pdc_mouse_status.button[i]) pdc_mouse_status.changes |= (1 << i); if (pdc_mouse_status.button[i] == BUTTON_MOVED) { /* Discard non-moved "moves" */ if (pdc_mouse_status.x == old_mouse_status.x && pdc_mouse_status.y == old_mouse_status.y) return -1; /* Motion events always flag the button as changed */ pdc_mouse_status.changes |= (1 << i); pdc_mouse_status.changes |= PDC_MOUSE_MOVED; break; } } old_mouse_status = pdc_mouse_status; /* Treat click events as release events for comparison purposes */ for (i = 0; i < 3; i++) { if (old_mouse_status.button[i] == BUTTON_CLICKED || old_mouse_status.button[i] == BUTTON_DOUBLE_CLICKED) old_mouse_status.button[i] = BUTTON_RELEASED; } /* Check for SHIFT/CONTROL/ALT */ if (MEV.dwControlKeyState & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED)) shift_flags |= BUTTON_ALT; if (MEV.dwControlKeyState & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED)) shift_flags |= BUTTON_CONTROL; if (MEV.dwControlKeyState & SHIFT_PRESSED) shift_flags |= BUTTON_SHIFT; if (shift_flags) { for (i = 0; i < 3; i++) { if (pdc_mouse_status.changes & (1 << i)) pdc_mouse_status.button[i] |= shift_flags; } } return KEY_MOUSE; }
void demoReadConChar(HANDLE hConOut) { BOOL bSuccess; INPUT_RECORD inputBuffer; DWORD dwStdInMode; HANDLE hStdIn; DWORD dwInputEvents; COORD coordLine; /* coordinates of where to read characters from */ CHAR *szLine; /* buffer to hold the line read from the console */ DWORD dwCharsRead; int i; setConTitle(__FILE__); myPuts(hConOut, "Click on any line containing characters. I will use\n" "ReadConsoleOutputCharacter to read that line of text into\n" "a buffer, then print that buffer to the console at the\n" "current cursor position. Hit ESC to return.\n\n"); hStdIn = GetStdHandle(STD_INPUT_HANDLE); PERR(hStdIn != INVALID_HANDLE_VALUE, "GetStdHandle"); /* save the console mode */ bSuccess = GetConsoleMode(hStdIn, &dwStdInMode); PERR(bSuccess, "GetConsoleMode"); /* enable mouse input */ bSuccess = SetConsoleMode(hStdIn, dwStdInMode | ENABLE_MOUSE_INPUT); PERR(bSuccess, "SetConsoleMode"); /* allocate space for one line */ szLine = (char *) malloc(getConX(hConOut)); PERR(szLine, "malloc"); for(;;) { /* get a single input event */ bSuccess = ReadConsoleInput(hStdIn, &inputBuffer, 1, &dwInputEvents); PERR(bSuccess, "ReadConsoleInput"); switch (inputBuffer.EventType) { case KEY_EVENT: /* is it an ESC key? */ if (inputBuffer.Event.KeyEvent.bKeyDown && inputBuffer.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) { /* set input mode back to what it was originally and return */ bSuccess = SetConsoleMode(hStdIn, dwStdInMode); PERR(bSuccess, "SetConsoleMode"); free(szLine); /* free allocated space for a text line */ return; } break; case MOUSE_EVENT: /* was this was a click event? Is any button down or not? */ if (inputBuffer.Event.MouseEvent.dwEventFlags != MOUSE_MOVED && inputBuffer.Event.MouseEvent.dwButtonState) { /* read the line where the mouse is, starting at column 0 */ coordLine.X = 0; coordLine.Y = inputBuffer.Event.MouseEvent.dwMousePosition.Y; bSuccess = ReadConsoleOutputCharacter(hConOut, szLine, getConX(hConOut), coordLine, &dwCharsRead); PERR(bSuccess, "ReadConsoleOutputCharacter"); /* strip trailing spaces */ i = getConX(hConOut) - 1; szLine[i--] = 0; /* null terminate */ while (szLine[i] == ' ') szLine[i--] = 0; myPuts(hConOut, szLine); } } /* switch */ } /* while */ }
void hold_console_open_on_error(void) { HANDLE hConIn; HANDLE hConErr; DWORD result; DWORD mode; time_t start; time_t remains; char *msg = "Note the errors or messages above, " "and press the <ESC> key to exit. "; CONSOLE_SCREEN_BUFFER_INFO coninfo; INPUT_RECORD in; char count[16]; #ifdef WIN32 /* The service parent cannot just 'pop' out of the main thread, * as it is about to try to do... * We must end this thread properly so the service control * thread exits gracefully. atexit()s registered in the running * apache_main thread _should_ have already been handled, so now * we can exit this thread and allow the service thread to exit. */ if (isWindowsNT() && isProcessService() && globdat.connected) { service_set_status(SERVICE_STOPPED); ExitThread(0); } #endif if (!real_exit_code) return; hConIn = GetStdHandle(STD_INPUT_HANDLE); hConErr = GetStdHandle(STD_ERROR_HANDLE); if ((hConIn == INVALID_HANDLE_VALUE) || (hConErr == INVALID_HANDLE_VALUE)) return; if (!WriteConsole(hConErr, msg, strlen(msg), &result, NULL) || !result) return; if (!GetConsoleScreenBufferInfo(hConErr, &coninfo)) return; if (isWindowsNT()) mode = ENABLE_MOUSE_INPUT | 0x80; else mode = ENABLE_MOUSE_INPUT; if (!SetConsoleMode(hConIn, mode)) return; start = time(NULL); do { while (PeekConsoleInput(hConIn, &in, 1, &result) && result) { if (!ReadConsoleInput(hConIn, &in, 1, &result) || !result) return; if ((in.EventType == KEY_EVENT) && in.Event.KeyEvent.bKeyDown && (in.Event.KeyEvent.uChar.AsciiChar == 27)) return; if (in.EventType == MOUSE_EVENT && (in.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK)) return; } remains = ((start + 30) - time(NULL)); sprintf (count, "%d...", remains); if (!SetConsoleCursorPosition(hConErr, coninfo.dwCursorPosition)) return; if (!WriteConsole(hConErr, count, strlen(count), &result, NULL) || !result) return; } while ((remains > 0) && WaitForSingleObject(hConIn, 1000) != WAIT_FAILED); }
static int readchar_win(ut32 usec) { int ch=0; BOOL ret; BOOL bCtrl = FALSE; DWORD mode, out; HANDLE h; INPUT_RECORD irInBuf[128]; int i; do_it_again: h = GetStdHandle (STD_INPUT_HANDLE); GetConsoleMode (h, &mode); SetConsoleMode (h, 0 | ENABLE_MOUSE_INPUT); // RAW if (usec) { if (WaitForSingleObject (h, usec) == WAIT_TIMEOUT) { return -1; } } ret = ReadConsoleInput (h, irInBuf, 128, &out); if (ret) { for (i = 0; i < out; i++) { if (irInBuf[i].EventType==MOUSE_EVENT) { switch (irInBuf[i].Event.MouseEvent.dwEventFlags) { case MOUSE_WHEELED: if (irInBuf[i].Event.MouseEvent.dwButtonState & 0xFF000000) ch='j'; else ch='k'; break; } } if (irInBuf[i].EventType==KEY_EVENT) { if (irInBuf[i].Event.KeyEvent.bKeyDown) { ch=irInBuf[i].Event.KeyEvent.uChar.AsciiChar; bCtrl=irInBuf[i].Event.KeyEvent.dwControlKeyState & 8; if (irInBuf[i].Event.KeyEvent.uChar.AsciiChar==0) { ch = 0; switch (irInBuf[i].Event.KeyEvent.wVirtualKeyCode) { case VK_DOWN: // key down ch = bCtrl ? 'J': 'j'; break; case VK_RIGHT: // key right ch = bCtrl ? 'L': 'l'; break; case VK_UP: // key up if (bCtrl) ch='K'; else ch='k'; break; case VK_LEFT: // key left if (bCtrl) ch='H'; else ch='h'; break; case VK_PRIOR: // key home if (bCtrl) ch='K'; else ch='K'; break; case VK_NEXT: // key end if (bCtrl) ch='J'; else ch='J'; break; case VK_F1: if (bCtrl) ch=R_CONS_KEY_F1; else ch=R_CONS_KEY_F1; break; case VK_F2: if (bCtrl) ch=R_CONS_KEY_F2; else ch=R_CONS_KEY_F2; break; case VK_F3: if (bCtrl) ch=R_CONS_KEY_F3; else ch=R_CONS_KEY_F3; break; case VK_F4: if (bCtrl) ch=R_CONS_KEY_F4; else ch=R_CONS_KEY_F4; break; case VK_F5: if (bCtrl) ch=0xcf5; else ch=R_CONS_KEY_F5; break; case VK_F6: if (bCtrl) ch=R_CONS_KEY_F6; else ch=R_CONS_KEY_F6; break; case VK_F7: if (bCtrl) ch=R_CONS_KEY_F7; else ch=R_CONS_KEY_F7; break; case VK_F8: if (bCtrl) ch=R_CONS_KEY_F8; else ch=R_CONS_KEY_F8; break; case VK_F9: if (bCtrl) ch=R_CONS_KEY_F9; else ch=R_CONS_KEY_F9; break; case VK_F10: if (bCtrl) ch=R_CONS_KEY_F10; else ch=R_CONS_KEY_F10; break; case VK_F11: if (bCtrl) ch=R_CONS_KEY_F11; else ch=R_CONS_KEY_F11; break; case VK_F12: if (bCtrl) ch=R_CONS_KEY_F12; else ch=R_CONS_KEY_F12; break; default: ch=0; break; } } } } } } FlushConsoleInputBuffer(h); SetConsoleMode (h, mode); if (ch == 0) { goto do_it_again; } /*r_cons_gotoxy (1, 2); r_cons_printf ("\n"); r_cons_printf ("| buf = %x |\n", ch); r_cons_printf ("\n"); r_cons_flush (); r_sys_sleep (1);*/ return ch; }
void __cdecl main(int argc, char **argv) { HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE); HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); int running = 1; #ifdef WIN32 if (IsDebuggerPresent()) { // turn on floating-point exceptions unsigned int prev; _clearfp(); _controlfp_s(&prev, 0, _EM_ZERODIVIDE|_EM_INVALID); } #endif // check the correct BASS was loaded if (HIWORD(BASS_GetVersion()) != BASSVERSION) { fprintf(stderr, "An incorrect version of BASS.DLL was loaded"); return; } // set the window title SetConsoleTitle(TEXT(title_text)); // set the console buffer size static const COORD bufferSize = { 80, 50 }; SetConsoleScreenBufferSize(hOut, bufferSize); // set the console window size static const SMALL_RECT windowSize = { 0, 0, 79, 49 }; SetConsoleWindowInfo(hOut, TRUE, &windowSize); // clear the window Clear(hOut); // hide the cursor static const CONSOLE_CURSOR_INFO cursorInfo = { 100, FALSE }; SetConsoleCursorInfo(hOut, &cursorInfo); // set input mode SetConsoleMode(hIn, 0); // 10ms update period const DWORD STREAM_UPDATE_PERIOD = 10; BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, STREAM_UPDATE_PERIOD); // initialize BASS sound library const DWORD STREAM_FREQUENCY = 48000; if (!BASS_Init(-1, STREAM_FREQUENCY, BASS_DEVICE_LATENCY, 0, NULL)) Error("Can't initialize device"); // get device info BASS_GetInfo(&info); // if the device's output rate is unknown default to stream frequency if (!info.freq) info.freq = STREAM_FREQUENCY; // debug print info DebugPrint("frequency: %d (min %d, max %d)\n", info.freq, info.minrate, info.maxrate); DebugPrint("device latency: %dms\n", info.latency); DebugPrint("device minbuf: %dms\n", info.minbuf); DebugPrint("ds version: %d (effects %s)\n", info.dsver, info.dsver < 8 ? "disabled" : "enabled"); // default buffer size = update period + 'minbuf' + 1ms extra margin BASS_SetConfig(BASS_CONFIG_BUFFER, STREAM_UPDATE_PERIOD + info.minbuf + 1); DebugPrint("using a %dms buffer\r", BASS_GetConfig(BASS_CONFIG_BUFFER)); // create a stream, stereo so that effects sound nice stream = BASS_StreamCreate(info.freq, 2, BASS_SAMPLE_FLOAT, (STREAMPROC*)WriteStream, 0); // set channel to apply effects fx_channel = stream; #ifdef BANDLIMITED_SAWTOOTH // initialize bandlimited sawtooth tables InitSawtooth(); #endif // initialize waves InitWave(); // enable the first oscillator osc_config[0].enable = true; // reset all controllers Control::ResetAll(); // start playing the audio stream BASS_ChannelPlay(stream, FALSE); // get the number of midi devices UINT midiInDevs = Midi::Input::GetNumDevices(); DebugPrint("MIDI input devices: %d\n", midiInDevs); // print device names for (UINT i = 0; i < midiInDevs; ++i) { MIDIINCAPS midiInCaps; if (Midi::Input::GetDeviceCaps(i, midiInCaps) == 0) { DebugPrint("%d: %s\n", i, midiInCaps.szPname); } } // if there are any devices available... if (midiInDevs > 0) { // open and start midi input // TO DO: select device number via a configuration setting Midi::Input::Open(0); Midi::Input::Start(); } // initialize to middle c note_most_recent = 60; voice_note[voice_most_recent] = unsigned char(note_most_recent); DisplaySpectrumAnalyzer displaySpectrumAnalyzer; DisplayKeyVolumeEnvelope displayKeyVolumeEnvelope; DisplayOscillatorWaveform displayOscillatorWaveform; DisplayOscillatorFrequency displayOscillatorFrequency; DisplayLowFrequencyOscillator displayLowFrequencyOscillator; DisplayFilterFrequency displayFilterFrequency; // initialize spectrum analyzer displaySpectrumAnalyzer.Init(stream, info); // initialize key display displayKeyVolumeEnvelope.Init(hOut); // show output scale and key octave PrintOutputScale(hOut); PrintKeyOctave(hOut); PrintGoToEffects(hOut); PrintAntialias(hOut); // show main page Menu::SetActivePage(hOut, Menu::PAGE_MAIN); while (running) { // if there are any pending input events... DWORD numEvents = 0; while (GetNumberOfConsoleInputEvents(hIn, &numEvents) && numEvents > 0) { // get the next input event INPUT_RECORD keyin; ReadConsoleInput(hIn, &keyin, 1, &numEvents); if (keyin.EventType == KEY_EVENT) { // handle interface keys if (keyin.Event.KeyEvent.bKeyDown) { WORD code = keyin.Event.KeyEvent.wVirtualKeyCode; DWORD modifiers = keyin.Event.KeyEvent.dwControlKeyState; if (code == VK_ESCAPE) { running = 0; break; } else if (code == VK_OEM_MINUS || code == VK_SUBTRACT) { Menu::UpdatePercentageProperty(output_scale, -1, modifiers, 0, 4); PrintOutputScale(hOut); } else if (code == VK_OEM_PLUS || code == VK_ADD) { Menu::UpdatePercentageProperty(output_scale, +1, modifiers, 0, 4); PrintOutputScale(hOut); } else if (code == VK_OEM_4) // '[' { if (keyboard_octave > 1) { for (int k = 0; k < KEYS; ++k) { if (key_down[k]) NoteOff(k + keyboard_octave * 12); } --keyboard_octave; for (int k = 0; k < KEYS; ++k) { if (key_down[k]) NoteOn(k + keyboard_octave * 12); } PrintKeyOctave(hOut); } } else if (code == VK_OEM_6) // ']' { if (keyboard_octave < 9) { for (int k = 0; k < KEYS; ++k) { if (key_down[k]) NoteOff(k + keyboard_octave * 12); } ++keyboard_octave; for (int k = 0; k < KEYS; ++k) { if (key_down[k]) NoteOn(k + keyboard_octave * 12); } PrintKeyOctave(hOut); } } else if (code == VK_F12) { use_antialias = !use_antialias; PrintAntialias(hOut); } else if (code >= VK_F1 && code < VK_F10) { Menu::SetActiveMenu(hOut, code - VK_F1); } else if (code == VK_F10) { PrintGoToEffects(hOut); Menu::SetActivePage(hOut, Menu::PAGE_MAIN); } else if (code == VK_F11) { PrintGoToMain(hOut); Menu::SetActivePage(hOut, Menu::PAGE_FX); } else if (code == VK_TAB) { if (modifiers & SHIFT_PRESSED) Menu::PrevMenu(hOut); else Menu::NextMenu(hOut); } else if (code == VK_UP || code == VK_DOWN || code == VK_RIGHT || code == VK_LEFT) { Menu::Handler(hOut, code, modifiers); } } // handle note keys for (int k = 0; k < KEYS; k++) { if (keyin.Event.KeyEvent.wVirtualKeyCode == keys[k]) { // key down bool down = (keyin.Event.KeyEvent.bKeyDown != 0); // if key down state changed... if (key_down[k] != down) { // update state key_down[k] = down; // if pressing the key if (down) { // note on NoteOn(k + keyboard_octave * 12); } else { // note off NoteOff(k + keyboard_octave * 12); } } break; } } } } // center frequency of the zeroth semitone band // (one octave down from the lowest key) float const freq_min = powf(2, float(keyboard_octave - 6)) * middle_c_frequency; // update the spectrum analyzer display displaySpectrumAnalyzer.Update(hOut, stream, info, freq_min); // update note key volume envelope display displayKeyVolumeEnvelope.Update(hOut); if (Menu::active_page == Menu::PAGE_MAIN) { // update the oscillator waveform display displayOscillatorWaveform.Update(hOut, info, voice_most_recent); // update the oscillator frequency displays for (int o = 0; o < NUM_OSCILLATORS; ++o) { if (osc_config[o].enable) displayOscillatorFrequency.Update(hOut, voice_most_recent, o); } // update the low-frequency oscillator display displayLowFrequencyOscillator.Update(hOut); // update the filter frequency display if (flt_config.enable) displayFilterFrequency.Update(hOut, voice_most_recent); } // show CPU usage PrintConsole(hOut, { 73, 49 }, "%6.2f%%", BASS_GetCPU()); // sleep for 1/60th of second Sleep(16); } if (midiInDevs) { // stop and close midi input Midi::Input::Stop(); Midi::Input::Close(); } // clean up spectrum analyzer displaySpectrumAnalyzer.Cleanup(stream); // clear the window Clear(hOut); BASS_Free(); }
/* ================ Sys_ConsoleInput ================ */ char *Sys_ConsoleInput (void) { INPUT_RECORD recs[1024]; int ch; DWORD dummy, numread, numevents; if (!dedicated || !dedicated->value) return NULL; for ( ;; ) { if (!GetNumberOfConsoleInputEvents (hinput, &numevents)) Sys_Error ("Error getting # of console events"); if (numevents <= 0) break; if (!ReadConsoleInput(hinput, recs, 1, &numread)) Sys_Error ("Error reading console input"); if (numread != 1) Sys_Error ("Couldn't read console input"); if (recs[0].EventType == KEY_EVENT) { if (!recs[0].Event.KeyEvent.bKeyDown) { ch = recs[0].Event.KeyEvent.uChar.AsciiChar; switch (ch) { case '\r': WriteFile(houtput, "\r\n", 2, &dummy, NULL); if (console_textlen) { console_text[console_textlen] = 0; console_textlen = 0; return console_text; } break; case '\b': if (console_textlen) { console_textlen--; WriteFile(houtput, "\b \b", 3, &dummy, NULL); } break; default: if (ch >= ' ') { if (console_textlen < sizeof(console_text)-2) { WriteFile(houtput, &ch, 1, &dummy, NULL); console_text[console_textlen] = ch; console_textlen++; } } break; } } } } return NULL; }
static int win32_get_event(caca_display_t *dp, caca_privevent_t *ev) { INPUT_RECORD rec; DWORD num; for( ; ; ) { GetNumberOfConsoleInputEvents(dp->drv.p->hin, &num); if(num == 0) break; ReadConsoleInput(dp->drv.p->hin, &rec, 1, &num); if(rec.EventType == KEY_EVENT) { if(rec.Event.KeyEvent.bKeyDown) ev->type = CACA_EVENT_KEY_PRESS; else ev->type = CACA_EVENT_KEY_RELEASE; if(rec.Event.KeyEvent.uChar.AsciiChar) { ev->data.key.ch = rec.Event.KeyEvent.uChar.AsciiChar; ev->data.key.utf32 = (uint32_t)ev->data.key.ch; ev->data.key.utf8[0] = ev->data.key.ch; ev->data.key.utf8[1] = '\0'; return 1; } else { switch (rec.Event.KeyEvent.wVirtualKeyCode) { case VK_TAB: ev->data.key.ch = '\t'; break; case VK_RETURN: ev->data.key.ch = '\r'; break; case VK_ESCAPE: ev->data.key.ch = '\033'; break; case VK_SPACE: ev->data.key.ch = ' '; break; case VK_DELETE: ev->data.key.ch = '\x7f'; break; case VK_LEFT: ev->data.key.ch = CACA_KEY_LEFT; break; case VK_RIGHT: ev->data.key.ch = CACA_KEY_RIGHT; break; case VK_UP: ev->data.key.ch = CACA_KEY_UP; break; case VK_DOWN: ev->data.key.ch = CACA_KEY_DOWN; break; case VK_INSERT: ev->data.key.ch = CACA_KEY_INSERT; break; case VK_HOME: ev->data.key.ch = CACA_KEY_HOME; break; case VK_END: ev->data.key.ch = CACA_KEY_END; break; case VK_PRIOR: ev->data.key.ch = CACA_KEY_PAGEUP; break; case VK_NEXT: ev->data.key.ch = CACA_KEY_PAGEDOWN; break; case VK_F1: ev->data.key.ch = CACA_KEY_F1; break; case VK_F2: ev->data.key.ch = CACA_KEY_F2; break; case VK_F3: ev->data.key.ch = CACA_KEY_F3; break; case VK_F4: ev->data.key.ch = CACA_KEY_F4; break; case VK_F5: ev->data.key.ch = CACA_KEY_F5; break; case VK_F6: ev->data.key.ch = CACA_KEY_F6; break; case VK_F7: ev->data.key.ch = CACA_KEY_F7; break; case VK_F8: ev->data.key.ch = CACA_KEY_F8; break; case VK_F9: ev->data.key.ch = CACA_KEY_F9; break; case VK_F10: ev->data.key.ch = CACA_KEY_F10; break; case VK_F11: ev->data.key.ch = CACA_KEY_F11; break; case VK_F12: ev->data.key.ch = CACA_KEY_F12; break; case VK_F13: ev->data.key.ch = CACA_KEY_F13; break; case VK_F14: ev->data.key.ch = CACA_KEY_F14; break; case VK_F15: ev->data.key.ch = CACA_KEY_F15; break; case VK_NUMPAD0: ev->data.key.ch = '0'; break; case VK_NUMPAD1: ev->data.key.ch = '1'; break; case VK_NUMPAD2: ev->data.key.ch = '2'; break; case VK_NUMPAD3: ev->data.key.ch = '3'; break; case VK_NUMPAD4: ev->data.key.ch = '4'; break; case VK_NUMPAD5: ev->data.key.ch = '5'; break; case VK_NUMPAD6: ev->data.key.ch = '6'; break; case VK_NUMPAD7: ev->data.key.ch = '7'; break; case VK_NUMPAD8: ev->data.key.ch = '8'; break; case VK_NUMPAD9: ev->data.key.ch = '9'; break; case VK_MULTIPLY: ev->data.key.ch = '*'; break; case VK_ADD: ev->data.key.ch = '+'; break; case VK_SEPARATOR: ev->data.key.ch = ','; break; case VK_SUBTRACT: ev->data.key.ch = '-'; break; case VK_DECIMAL: ev->data.key.ch = '.'; break; case VK_DIVIDE: ev->data.key.ch = '/'; break; default: ev->type = CACA_EVENT_NONE; return 0; } if ((ev->data.key.ch > 0) && (ev->data.key.ch <= 0x7f)) { ev->data.key.utf32 = (uint32_t)ev->data.key.ch; ev->data.key.utf8[0] = ev->data.key.ch; ev->data.key.utf8[1] = '\0'; } else { ev->data.key.utf32 = 0; ev->data.key.utf8[0] = '\0'; } return 1; } } if(rec.EventType == MOUSE_EVENT) { if(rec.Event.MouseEvent.dwEventFlags == 0) { if(rec.Event.MouseEvent.dwButtonState & 0x01) { ev->type = CACA_EVENT_MOUSE_PRESS; ev->data.mouse.button = 1; return 1; } if(rec.Event.MouseEvent.dwButtonState & 0x02) { ev->type = CACA_EVENT_MOUSE_PRESS; ev->data.mouse.button = 2; return 1; } } else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_MOVED) { COORD pos = rec.Event.MouseEvent.dwMousePosition; if(dp->mouse.x == pos.X && dp->mouse.y == pos.Y) continue; dp->mouse.x = pos.X; dp->mouse.y = pos.Y; ev->type = CACA_EVENT_MOUSE_MOTION; ev->data.mouse.x = dp->mouse.x; ev->data.mouse.y = dp->mouse.y; return 1; } #if 0 else if(rec.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK) { cout << rec.Event.MouseEvent.dwMousePosition.X << "," << rec.Event.MouseEvent.dwMousePosition.Y << " " << flush; } else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_WHEELED) { SetConsoleCursorPosition(hOut, WheelWhere); if(rec.Event.MouseEvent.dwButtonState & 0xFF000000) cout << "Down" << flush; else cout << "Up " << flush; } #endif } /* Unknown event */ ev->type = CACA_EVENT_NONE; return 0; } /* No event */ ev->type = CACA_EVENT_NONE; return 0; }
//마우스 클릭 이벤트 함수. //마우스 이벤트에 해당하는 값을 리턴함 int MouseClickTest() { INPUT_RECORD Inrec; //마우스나 키보드 이벤트를 저장한 구조체 DWORD evRead; HANDLE hStdIn=NULL; DWORD dwMode; int nClickNum=0; GetConsoleMode(hStdIn, &dwMode); hStdIn = GetStdHandle(STD_INPUT_HANDLE); GetConsoleMode(hStdIn, &dwMode); if(!(dwMode & ENABLE_MOUSE_INPUT)) { if(TRUE != SetConsoleMode( hStdIn, dwMode | ENABLE_MOUSE_INPUT)) { return 0; } } PeekConsoleInput(hStdIn, &Inrec, 1, &evRead); if( evRead>0) { ReadConsoleInput(hStdIn, &Inrec, 1, &evRead); switch (Inrec.EventType ) { case MOUSE_EVENT: { //FROM_LEFT_1ST_BUTTON_PRESSED 이건1 //FROM_LEFT_2ND_BUTTON_PRESSED 이건2 if(FROM_LEFT_1ST_BUTTON_PRESSED & Inrec.Event.MouseEvent.dwButtonState) //왼쪽클릭 입력처리 { nClickNum |=0x01; } if(FROM_LEFT_2ND_BUTTON_PRESSED & Inrec.Event.MouseEvent.dwButtonState) // 휠 클릭 입력처리 { nClickNum |=0x04; } if(RIGHTMOST_BUTTON_PRESSED & Inrec.Event.MouseEvent.dwButtonState) // 오른쪽 클릭 입력처리 { nClickNum|=0x02; } if(DOUBLE_CLICK & Inrec.Event.MouseEvent.dwEventFlags) // { nClickNum = 0x08; _tprintf(_T("%d\n"),nClickNum); } break; } case KEY_EVENT: { _tprintf(_T("No key\n")); break; } } } //gotoxy(0, 0); //printf("%d,%d",nClickNum&0x01, nClickNum&0x02); return nClickNum; }
//! runs the device. Returns false if device wants to be deleted bool CIrrDeviceConsole::run() { // increment timer os::Timer::tick(); // process Windows console input #ifdef _IRR_WINDOWS_NT_CONSOLE_ INPUT_RECORD in; DWORD oldMode; DWORD count, waste; // get old input mode GetConsoleMode(WindowsSTDIn, &oldMode); SetConsoleMode(WindowsSTDIn, ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT); GetNumberOfConsoleInputEvents(WindowsSTDIn, &count); // read keyboard and mouse input while (count) { ReadConsoleInput(WindowsSTDIn, &in, 1, &waste ); switch(in.EventType) { case KEY_EVENT: { SEvent e; e.EventType = EET_KEY_INPUT_EVENT; e.KeyInput.PressedDown = (in.Event.KeyEvent.bKeyDown == TRUE); e.KeyInput.Control = (in.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0; e.KeyInput.Shift = (in.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED) != 0; e.KeyInput.Key = EKEY_CODE(in.Event.KeyEvent.wVirtualKeyCode); e.KeyInput.Char = in.Event.KeyEvent.uChar.UnicodeChar; postEventFromUser(e); break; } case MOUSE_EVENT: { SEvent e; e.EventType = EET_MOUSE_INPUT_EVENT; e.MouseInput.X = in.Event.MouseEvent.dwMousePosition.X; e.MouseInput.Y = in.Event.MouseEvent.dwMousePosition.Y; e.MouseInput.Wheel = 0.f; e.MouseInput.ButtonStates = ( (in.Event.MouseEvent.dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) ? EMBSM_LEFT : 0 ) | ( (in.Event.MouseEvent.dwButtonState & RIGHTMOST_BUTTON_PRESSED) ? EMBSM_RIGHT : 0 ) | ( (in.Event.MouseEvent.dwButtonState & FROM_LEFT_2ND_BUTTON_PRESSED) ? EMBSM_MIDDLE : 0 ) | ( (in.Event.MouseEvent.dwButtonState & FROM_LEFT_3RD_BUTTON_PRESSED) ? EMBSM_EXTRA1 : 0 ) | ( (in.Event.MouseEvent.dwButtonState & FROM_LEFT_4TH_BUTTON_PRESSED) ? EMBSM_EXTRA2 : 0 ); if (in.Event.MouseEvent.dwEventFlags & MOUSE_MOVED) { CursorControl->setPosition(core::position2di(e.MouseInput.X, e.MouseInput.Y)); // create mouse moved event e.MouseInput.Event = EMIE_MOUSE_MOVED; postEventFromUser(e); } if (in.Event.MouseEvent.dwEventFlags & MOUSE_WHEELED) { e.MouseInput.Event = EMIE_MOUSE_WHEEL; e.MouseInput.Wheel = (in.Event.MouseEvent.dwButtonState & 0xFF000000) ? -1.0f : 1.0f; postEventFromUser(e); } if ( (MouseButtonStates & EMBSM_LEFT) != (e.MouseInput.ButtonStates & EMBSM_LEFT) ) { e.MouseInput.Event = (e.MouseInput.ButtonStates & EMBSM_LEFT) ? EMIE_LMOUSE_PRESSED_DOWN : EMIE_LMOUSE_LEFT_UP; postEventFromUser(e); } if ( (MouseButtonStates & EMBSM_RIGHT) != (e.MouseInput.ButtonStates & EMBSM_RIGHT) ) { e.MouseInput.Event = (e.MouseInput.ButtonStates & EMBSM_RIGHT) ? EMIE_RMOUSE_PRESSED_DOWN : EMIE_RMOUSE_LEFT_UP; postEventFromUser(e); } if ( (MouseButtonStates & EMBSM_MIDDLE) != (e.MouseInput.ButtonStates & EMBSM_MIDDLE) ) { e.MouseInput.Event = (e.MouseInput.ButtonStates & EMBSM_MIDDLE) ? EMIE_MMOUSE_PRESSED_DOWN : EMIE_MMOUSE_LEFT_UP; postEventFromUser(e); } // save current button states MouseButtonStates = e.MouseInput.ButtonStates; break; } case WINDOW_BUFFER_SIZE_EVENT: VideoDriver->OnResize( core::dimension2d<u32>(in.Event.WindowBufferSizeEvent.dwSize.X, in.Event.WindowBufferSizeEvent.dwSize.Y)); break; case FOCUS_EVENT: IsWindowFocused = (in.Event.FocusEvent.bSetFocus == TRUE); break; default: break; } GetNumberOfConsoleInputEvents(WindowsSTDIn, &count); } // set input mode SetConsoleMode(WindowsSTDIn, oldMode); #else // todo: keyboard input from terminal in raw mode #endif return !Close; }
PINPUT_RECORD NextEvent ( BOOL fAdvance, BOOL fWait ) /*++ Routine Description: Returns pointer to next event record. Arguments: fAdvance - Supplies a flag: if TRUE: Advance to next event record if FALSE: Do not advance to next event record fWait - Supplies a flag: if TRUE, the blocks until an event is ready. if FALSE, return immediately. Return Value: Pointer to event record, or NULL. --*/ { PINPUT_RECORD pEvent; BOOL Success; EnterCriticalSection(&(EventBuffer.CriticalSection)); // // If the busy flag is set, then the buffer is in the process of // being read. Only one thread should want to wait, so it is // safe to simply return. // if ( EventBuffer.BusyFlag ) { assert( !fWait ); LeaveCriticalSection(&(EventBuffer.CriticalSection)); return NULL; } if (EventBuffer.NumberOfEvents == 0) { // // No events in buffer, read as many as we can // DWORD NumberOfEvents; // // If the buffer is too big, resize it // if ( EventBuffer.MaxEvents > MAX_EVENTS ) { EventBuffer.EventBuffer = REALLOC( EventBuffer.EventBuffer, MAX_EVENTS * sizeof( INPUT_RECORD ) ); EventBuffer.MaxEvents = MAX_EVENTS; assert( EventBuffer.EventBuffer ); if ( !EventBuffer.EventBuffer ) { CleanExit( 1, 0 ); } } Success = PeekConsoleInput( hInput, EventBuffer.EventBuffer, EventBuffer.MaxEvents, &NumberOfEvents); if ((!Success || (NumberOfEvents == 0)) && (!fWait)) { // // No events available and don't want to wait, // return. // LeaveCriticalSection(&(EventBuffer.CriticalSection)); return NULL; } // // Since we will block, we have to leave the critical section. // We set the Busy flag to indicate that the buffer is being // read. // EventBuffer.BusyFlag = TRUE; LeaveCriticalSection(&(EventBuffer.CriticalSection)); Success = ReadConsoleInput( hInput, EventBuffer.EventBuffer, NumberOfEvents, &EventBuffer.NumberOfEvents); EnterCriticalSection(&(EventBuffer.CriticalSection)); EventBuffer.BusyFlag = FALSE; if (!Success) { #if defined( DEBUG ) // OutputDebugString(" Error: Cannot read console events\n"); assert( Success ); #endif EventBuffer.NumberOfEvents = 0; } EventBuffer.EventIndex = 0; } if (EventBuffer.NumberOfEvents == 0) { #if defined( DEBUG ) // OutputDebugString(" Error: Cannot read console events\n"); assert( Success ); #endif return NULL; } pEvent = EventBuffer.EventBuffer + EventBuffer.EventIndex; // // If Advance flag is set, we advance the pointer to the next // record. // if (fAdvance) { if (--(EventBuffer.NumberOfEvents)) { switch (EVENT_TYPE(pEvent)) { case KEY_EVENT: case MOUSE_EVENT: case WINDOW_BUFFER_SIZE_EVENT: case MENU_EVENT: case FOCUS_EVENT: (EventBuffer.EventIndex)++; break; default: #if defined( DEBUG) sprintf(DbgBuffer, "WARNING: unknown event type %X\n", EVENT_TYPE(pEvent)); OutputDebugString(DbgBuffer); #endif (EventBuffer.EventIndex)++; break; } } } LeaveCriticalSection(&(EventBuffer.CriticalSection)); return pEvent; }
/* * Sys_ConsoleInput */ char *Sys_ConsoleInput( void ) { INPUT_RECORD rec; int ch; DWORD dummy; DWORD numread, numevents; if( !dedicated || !dedicated->integer ) return NULL; if( !hinput ) hinput = GetStdHandle( STD_INPUT_HANDLE ); if( !houtput ) houtput = GetStdHandle( STD_OUTPUT_HANDLE ); for(;; ) { if( !GetNumberOfConsoleInputEvents( hinput, &numevents ) ) Sys_Error( "Error getting # of console events" ); if( numevents <= 0 ) break; if( !ReadConsoleInput( hinput, &rec, 1, &numread ) ) Sys_Error( "Error reading console input" ); if( numread != 1 ) Sys_Error( "Couldn't read console input" ); if( rec.EventType == KEY_EVENT ) { if( !rec.Event.KeyEvent.bKeyDown ) { ch = rec.Event.KeyEvent.uChar.AsciiChar; switch( ch ) { case '\r': WriteFile( houtput, "\r\n", 2, &dummy, NULL ); if( console_textlen ) { console_text[console_textlen] = 0; console_textlen = 0; return OEM_to_utf8( console_text ); } break; case '\b': if( console_textlen ) { console_textlen--; WriteFile( houtput, "\b \b", 3, &dummy, NULL ); } break; default: if( ( unsigned char )ch >= ' ' ) { if( console_textlen < sizeof( console_text )-2 ) { WriteFile( houtput, &ch, 1, &dummy, NULL ); console_text[console_textlen] = ch; console_textlen++; } } break; } } } } return NULL; }
static DWORD WINAPI console_select_thread (void *arg) { struct serial *scb = arg; struct ser_console_state *state; int event_index; HANDLE h; state = scb->state; h = (HANDLE) _get_osfhandle (scb->fd); while (1) { HANDLE wait_events[2]; INPUT_RECORD record; DWORD n_records; select_thread_wait (state); while (1) { wait_events[0] = state->stop_select; wait_events[1] = h; event_index = WaitForMultipleObjects (2, wait_events, FALSE, INFINITE); if (event_index == WAIT_OBJECT_0 || WaitForSingleObject (state->stop_select, 0) == WAIT_OBJECT_0) break; if (event_index != WAIT_OBJECT_0 + 1) { /* Wait must have failed; assume an error has occured, e.g. the handle has been closed. */ SetEvent (state->except_event); break; } /* We've got a pending event on the console. See if it's of interest. */ if (!PeekConsoleInput (h, &record, 1, &n_records) || n_records != 1) { /* Something went wrong. Maybe the console is gone. */ SetEvent (state->except_event); break; } if (record.EventType == KEY_EVENT && record.Event.KeyEvent.bKeyDown) { WORD keycode = record.Event.KeyEvent.wVirtualKeyCode; /* Ignore events containing only control keys. We must recognize "enhanced" keys which we are interested in reading via getch, if they do not map to ASCII. But we do not want to report input available for e.g. the control key alone. */ if (record.Event.KeyEvent.uChar.AsciiChar != 0 || keycode == VK_PRIOR || keycode == VK_NEXT || keycode == VK_END || keycode == VK_HOME || keycode == VK_LEFT || keycode == VK_UP || keycode == VK_RIGHT || keycode == VK_DOWN || keycode == VK_INSERT || keycode == VK_DELETE) { /* This is really a keypress. */ SetEvent (state->read_event); break; } } /* Otherwise discard it and wait again. */ ReadConsoleInput (h, &record, 1, &n_records); } SetEvent(state->have_stopped); } }
//FIXME utf8 input char *CON_Input( void ) { INPUT_RECORD buff[ MAX_EDIT_LINE ]; DWORD count = 0, events = 0; WORD key = 0; int i; int newlinepos = -1; if( !GetNumberOfConsoleInputEvents( qconsole_hin, &events ) ) return NULL; if( events < 1 ) return NULL; // if we have overflowed, start dropping oldest input events if( events >= MAX_EDIT_LINE ) { ReadConsoleInput( qconsole_hin, buff, 1, &events ); return NULL; } if( !ReadConsoleInput( qconsole_hin, buff, events, &count ) ) return NULL; FlushConsoleInputBuffer( qconsole_hin ); for( i = 0; i < count; i++ ) { if( buff[ i ].EventType != KEY_EVENT ) continue; if( !buff[ i ].Event.KeyEvent.bKeyDown ) continue; key = buff[ i ].Event.KeyEvent.wVirtualKeyCode; if( key == VK_RETURN ) { newlinepos = i; qconsole_cursor = 0; break; } else if( key == VK_UP ) { CON_HistPrev(); break; } else if( key == VK_DOWN ) { CON_HistNext(); break; } else if( key == VK_LEFT ) { qconsole_cursor--; if ( qconsole_cursor < 0 ) { qconsole_cursor = 0; } break; } else if( key == VK_RIGHT ) { qconsole_cursor++; if ( qconsole_cursor > qconsole_linelen ) { qconsole_cursor = qconsole_linelen; } break; } else if( key == VK_HOME ) { qconsole_cursor = 0; break; } else if( key == VK_END ) { qconsole_cursor = qconsole_linelen; break; } else if( key == VK_TAB ) { field_t f; const char *fieldString; //Q_strncpyz( f.buffer, qconsole_line, sizeof( f.buffer ) ); Field_SetBuffer(&f, qconsole_line, sizeof(qconsole_line), 0); Field_AutoComplete( &f ); //Q_strncpyz( qconsole_line, f.buffer, sizeof( qconsole_line ) ); fieldString = Field_AsStr(&f, 0, 0); Q_strncpyz(qconsole_line, fieldString, sizeof(qconsole_line)); qconsole_linelen = strlen( qconsole_line ); qconsole_cursor = qconsole_linelen; break; } if( qconsole_linelen < sizeof( qconsole_line ) - 1 ) { char c = buff[ i ].Event.KeyEvent.uChar.AsciiChar; if( key == VK_BACK ) { if ( qconsole_cursor > 0 ) { int newlen = ( qconsole_linelen > 0 ) ? qconsole_linelen - 1 : 0; if ( qconsole_cursor < qconsole_linelen ) { memmove( qconsole_line + qconsole_cursor - 1, qconsole_line + qconsole_cursor, qconsole_linelen - qconsole_cursor ); } qconsole_line[ newlen ] = '\0'; qconsole_linelen = newlen; qconsole_cursor--; } } else if( c ) { if ( qconsole_linelen > qconsole_cursor ) { memmove( qconsole_line + qconsole_cursor + 1, qconsole_line + qconsole_cursor, qconsole_linelen - qconsole_cursor ); } qconsole_line[ qconsole_cursor++ ] = c; qconsole_linelen++; qconsole_line[ qconsole_linelen ] = '\0'; } } } if( newlinepos < 0) { CON_Show(); return NULL; } if( !qconsole_linelen ) { CON_Show(); Com_Printf( "\n" ); return NULL; } qconsole_linelen = 0; CON_Show(); CON_HistAdd(); Com_Printf( "%s\n", qconsole_line ); return qconsole_line; }
static int win32read(char *c) { DWORD foo; INPUT_RECORD b; KEY_EVENT_RECORD e; while (1) { if (!ReadConsoleInput(hIn, &b, 1, &foo)) return 0; if (!foo) return 0; if (b.EventType == KEY_EVENT && b.Event.KeyEvent.bKeyDown) { e = b.Event.KeyEvent; *c = b.Event.KeyEvent.uChar.AsciiChar; //if (e.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) { /* Alt+key ignored */ //} else if (e.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) { /* Ctrl+Key */ switch (*c) { case 'D': *c = 4; return 1; case 'C': *c = 3; return 1; case 'H': *c = 8; return 1; case 'T': *c = 20; return 1; case 'B': /* ctrl-b, left_arrow */ *c = 2; return 1; case 'F': /* ctrl-f right_arrow*/ *c = 6; return 1; case 'P': /* ctrl-p up_arrow*/ *c = 16; return 1; case 'N': /* ctrl-n down_arrow*/ *c = 14; return 1; case 'U': /* Ctrl+u, delete the whole line. */ *c = 21; return 1; case 'K': /* Ctrl+k, delete from current to end of line. */ *c = 11; return 1; case 'A': /* Ctrl+a, go to the start of the line */ *c = 1; return 1; case 'E': /* ctrl+e, go to the end of the line */ *c = 5; return 1; } /* Other Ctrl+KEYs ignored */ } else { switch (e.wVirtualKeyCode) { case VK_ESCAPE: /* ignore - send ctrl-c, will return -1 */ *c = 3; return 1; case VK_RETURN: /* enter */ *c = 13; return 1; case VK_LEFT: /* left */ *c = 2; return 1; case VK_RIGHT: /* right */ *c = 6; return 1; case VK_UP: /* up */ *c = 16; return 1; case VK_DOWN: /* down */ *c = 14; return 1; case VK_HOME: *c = 1; return 1; case VK_END: *c = 5; return 1; case VK_BACK: *c = 8; return 1; case VK_DELETE: *c = 127; return 1; default: if (*c) return 1; } } } } return -1; /* Makes compiler happy */ }
int do_everything(int argc, LPCWSTR argv[]) { HRESULT hr = S_OK; // parse command line CPrefs prefs(argc, argv, hr); if (FAILED(hr)) { ERR(L"CPrefs::CPrefs constructor failed: hr = 0x%08x", hr); return -__LINE__; } if (S_FALSE == hr) { // nothing to do return 0; } // create a "loopback capture has started" event HANDLE hStartedEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (NULL == hStartedEvent) { ERR(L"CreateEvent failed: last error is %u", GetLastError()); return -__LINE__; } CloseHandleOnExit closeStartedEvent(hStartedEvent); // create a "stop capturing now" event HANDLE hStopEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (NULL == hStopEvent) { ERR(L"CreateEvent failed: last error is %u", GetLastError()); return -__LINE__; } CloseHandleOnExit closeStopEvent(hStopEvent); // create arguments for loopback capture thread LoopbackCaptureThreadFunctionArguments threadArgs; threadArgs.hr = E_UNEXPECTED; // thread will overwrite this threadArgs.pMMDevice = prefs.m_pMMDevice; threadArgs.bInt16 = prefs.m_bInt16; threadArgs.hFile = prefs.m_hFile; threadArgs.hStartedEvent = hStartedEvent; threadArgs.hStopEvent = hStopEvent; threadArgs.nFrames = 0; HANDLE hThread = CreateThread( NULL, 0, LoopbackCaptureThreadFunction, &threadArgs, 0, NULL ); if (NULL == hThread) { ERR(L"CreateThread failed: last error is %u", GetLastError()); return -__LINE__; } CloseHandleOnExit closeThread(hThread); // wait for either capture to start or the thread to end HANDLE waitArray[2] = { hStartedEvent, hThread }; DWORD dwWaitResult; dwWaitResult = WaitForMultipleObjects( _countof(waitArray), waitArray, FALSE, INFINITE ); if (WAIT_OBJECT_0 + 1 == dwWaitResult) { ERR(L"Thread aborted before starting to loopback capture: hr = 0x%08x", threadArgs.hr); return -__LINE__; } if (WAIT_OBJECT_0 != dwWaitResult) { ERR(L"Unexpected WaitForMultipleObjects return value %u", dwWaitResult); return -__LINE__; } // at this point capture is running // wait for the user to press a key or for capture to error out { WaitForSingleObjectOnExit waitForThread(hThread); SetEventOnExit setStopEvent(hStopEvent); HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE); if (INVALID_HANDLE_VALUE == hStdIn) { ERR(L"GetStdHandle returned INVALID_HANDLE_VALUE: last error is %u", GetLastError()); return -__LINE__; } LOG(L"%s", L"Press Enter to quit..."); HANDLE rhHandles[2] = { hThread, hStdIn }; bool bKeepWaiting = true; while (bKeepWaiting) { dwWaitResult = WaitForMultipleObjects(2, rhHandles, FALSE, INFINITE); switch (dwWaitResult) { case WAIT_OBJECT_0: // hThread ERR(L"%s", L"The thread terminated early - something bad happened"); bKeepWaiting = false; break; case WAIT_OBJECT_0 + 1: // hStdIn // see if any of them was an Enter key-up event INPUT_RECORD rInput[128]; DWORD nEvents; if (!ReadConsoleInput(hStdIn, rInput, _countof(rInput), &nEvents)) { ERR(L"ReadConsoleInput failed: last error is %u", GetLastError()); bKeepWaiting = false; } else { for (DWORD i = 0; i < nEvents; i++) { if ( KEY_EVENT == rInput[i].EventType && VK_RETURN == rInput[i].Event.KeyEvent.wVirtualKeyCode && !rInput[i].Event.KeyEvent.bKeyDown ) { LOG(L"%s", L"Stopping capture..."); bKeepWaiting = false; break; } } // if none of them were Enter key-up events, // continue waiting } break; default: ERR(L"WaitForMultipleObjects returned unexpected value 0x%08x", dwWaitResult); bKeepWaiting = false; break; } // switch } // while } // naked scope // at this point the thread is definitely finished DWORD exitCode; if (!GetExitCodeThread(hThread, &exitCode)) { ERR(L"GetExitCodeThread failed: last error is %u", GetLastError()); return -__LINE__; } if (0 != exitCode) { ERR(L"Loopback capture thread exit code is %u; expected 0", exitCode); return -__LINE__; } if (S_OK != threadArgs.hr) { ERR(L"Thread HRESULT is 0x%08x", threadArgs.hr); return -__LINE__; } // everything went well... fixup the fact chunk in the file MMRESULT result = mmioClose(prefs.m_hFile, 0); prefs.m_hFile = NULL; if (MMSYSERR_NOERROR != result) { ERR(L"mmioClose failed: MMSYSERR = %u", result); return -__LINE__; } // reopen the file in read/write mode MMIOINFO mi = {0}; prefs.m_hFile = mmioOpen(const_cast<LPWSTR>(prefs.m_szFilename), &mi, MMIO_READWRITE); if (NULL == prefs.m_hFile) { ERR(L"mmioOpen(\"%ls\", ...) failed. wErrorRet == %u", prefs.m_szFilename, mi.wErrorRet); return -__LINE__; } // descend into the RIFF/WAVE chunk MMCKINFO ckRIFF = {0}; ckRIFF.ckid = MAKEFOURCC('W', 'A', 'V', 'E'); // this is right for mmioDescend result = mmioDescend(prefs.m_hFile, &ckRIFF, NULL, MMIO_FINDRIFF); if (MMSYSERR_NOERROR != result) { ERR(L"mmioDescend(\"WAVE\") failed: MMSYSERR = %u", result); return -__LINE__; } // descend into the fact chunk MMCKINFO ckFact = {0}; ckFact.ckid = MAKEFOURCC('f', 'a', 'c', 't'); result = mmioDescend(prefs.m_hFile, &ckFact, &ckRIFF, MMIO_FINDCHUNK); if (MMSYSERR_NOERROR != result) { ERR(L"mmioDescend(\"fact\") failed: MMSYSERR = %u", result); return -__LINE__; } // write the correct data to the fact chunk LONG lBytesWritten = mmioWrite( prefs.m_hFile, reinterpret_cast<PCHAR>(&threadArgs.nFrames), sizeof(threadArgs.nFrames) ); if (lBytesWritten != sizeof(threadArgs.nFrames)) { ERR(L"Updating the fact chunk wrote %u bytes; expected %u", lBytesWritten, (UINT32)sizeof(threadArgs.nFrames)); return -__LINE__; } // ascend out of the fact chunk result = mmioAscend(prefs.m_hFile, &ckFact, 0); if (MMSYSERR_NOERROR != result) { ERR(L"mmioAscend(\"fact\") failed: MMSYSERR = %u", result); return -__LINE__; } // let prefs' destructor call mmioClose return 0; }
static DWORD WINAPI select_ws_wait_thread(LPVOID lpParameter) { struct select_ws_wait_data *data; HANDLE handle, handles[2]; INPUT_RECORD inputrecord; LARGE_INTEGER size, pos; DWORD type, length; /* retrieve handles from internal structure */ data = (struct select_ws_wait_data *) lpParameter; if(data) { handle = data->handle; handles[0] = data->event; handles[1] = handle; free(data); } else return (DWORD)-1; /* retrieve the type of file to wait on */ type = GetFileType(handle); switch(type) { case FILE_TYPE_DISK: /* The handle represents a file on disk, this means: * - WaitForMultipleObjectsEx will always be signalled for it. * - comparison of current position in file and total size of * the file can be used to check if we reached the end yet. * * Approach: Loop till either the internal event is signalled * or if the end of the file has already been reached. */ while(WaitForMultipleObjectsEx(1, handles, FALSE, 0, FALSE) == WAIT_TIMEOUT) { /* get total size of file */ length = 0; size.QuadPart = 0; size.LowPart = GetFileSize(handle, &length); if((size.LowPart != INVALID_FILE_SIZE) || (GetLastError() == NO_ERROR)) { size.HighPart = length; /* get the current position within the file */ pos.QuadPart = 0; pos.LowPart = SetFilePointer(handle, 0, &pos.HighPart, FILE_CURRENT); if((pos.LowPart != INVALID_SET_FILE_POINTER) || (GetLastError() == NO_ERROR)) { /* compare position with size, abort if not equal */ if(size.QuadPart == pos.QuadPart) { /* sleep and continue waiting */ SleepEx(0, FALSE); continue; } } } /* there is some data available, stop waiting */ break; } break; case FILE_TYPE_CHAR: /* The handle represents a character input, this means: * - WaitForMultipleObjectsEx will be signalled on any kind of input, * including mouse and window size events we do not care about. * * Approach: Loop till either the internal event is signalled * or we get signalled for an actual key-event. */ while(WaitForMultipleObjectsEx(2, handles, FALSE, INFINITE, FALSE) == WAIT_OBJECT_0 + 1) { /* check if this is an actual console handle */ length = 0; if(GetConsoleMode(handle, &length)) { /* retrieve an event from the console buffer */ length = 0; if(PeekConsoleInput(handle, &inputrecord, 1, &length)) { /* check if the event is not an actual key-event */ if(length == 1 && inputrecord.EventType != KEY_EVENT) { /* purge the non-key-event and continue waiting */ ReadConsoleInput(handle, &inputrecord, 1, &length); continue; } } } /* there is some data available, stop waiting */ break; } break; case FILE_TYPE_PIPE: /* The handle represents an anonymous or named pipe, this means: * - WaitForMultipleObjectsEx will always be signalled for it. * - peek into the pipe and retrieve the amount of data available. * * Approach: Loop till either the internal event is signalled * or there is data in the pipe available for reading. */ while(WaitForMultipleObjectsEx(1, handles, FALSE, 0, FALSE) == WAIT_TIMEOUT) { /* peek into the pipe and retrieve the amount of data available */ length = 0; if(PeekNamedPipe(handle, NULL, 0, NULL, &length, NULL)) { /* if there is no data available, sleep and continue waiting */ if(length == 0) { SleepEx(0, FALSE); continue; } } else { /* if the pipe has been closed, sleep and continue waiting */ if(GetLastError() == ERROR_BROKEN_PIPE) { SleepEx(0, FALSE); continue; } } /* there is some data available, stop waiting */ break; } break; default: /* The handle has an unknown type, try to wait on it */ WaitForMultipleObjectsEx(2, handles, FALSE, INFINITE, FALSE); break; } return 0; }
bool RendererConsole::updateInput() { DWORD numEvents = 0; GetNumberOfConsoleInputEvents(_inputHandle, &numEvents); if (numEvents == 0) { return false; } _events.clear(); _events.resize(numEvents); DWORD numEventsRead = 0; ReadConsoleInput(_inputHandle, &_events[0], numEvents, &numEventsRead); for (DWORD i = 0; i < numEventsRead; i++) { switch (_events[i].EventType) { case KEY_EVENT: switch (_events[i].Event.KeyEvent.wVirtualKeyCode) { case VK_ESCAPE: if (!_onQuitListeners.empty()) { for (auto listener : _onQuitListeners) { listener(); } return true; } break; case VK_RETURN: if (!_onRestartListeners.empty()) { for (auto listener : _onRestartListeners) { listener(); } return true; } break; case VK_LEFT: if (!_onMoveLeftListener.empty()) { for (auto listener : _onMoveLeftListener) { listener(); } return true; } break; case VK_RIGHT: if (!_onMoveRightListener.empty()) { for (auto listener : _onMoveRightListener) { listener(); } return true; } break; case VK_DOWN: if (!_onMoveDownListener.empty()) { for (auto listener : _onMoveDownListener) { listener(); } return true; } break; case VK_UP: if (!_onMoveUpListener.empty()) { for (auto listener : _onMoveUpListener) { listener(); } return true; } break; } } } return false; }
/* main readline function */ char *readline(const char *prompt) { wchar_t buf[_EL_CONSOLE_BUF_LEN]; char **array = NULL; char *ret_string = NULL; int start = 0; int end = 0; int compl_pos = -1; int n = 0; int index = 0; int len = 0; int line_len = 0; int old_width = 0; int width = 0; UINT32 ctrl = 0; UINT32 special = 0; COORD coord; DWORD count = 0; INPUT_RECORD irBuffer; CONSOLE_SCREEN_BUFFER_INFO sbInfo; static int piped_input_finished = FALSE; if (piped_input_finished) { return NULL; } _el_ctrl_c_pressed = FALSE; _el_line_buffer = NULL; _el_temp_print = NULL; _el_next_compl = NULL; rl_line_buffer = NULL; _el_file_name = NULL; _el_dir_name = NULL; _el_old_arg = NULL; _el_wide = NULL; _el_text = NULL; _el_text_mb = NULL; _el_compl_array = NULL; _el_completer_word_break_characters = NULL; rl_point = 0; rl_attempted_completion_over = 0; _el_compl_index = 0; _el_n_compl = 0; _el_h_in = NULL; _el_h_out = NULL; wcscpy_s(_el_basic_file_break_characters, _EL_MAX_FILE_BREAK_CHARACTERS, _EL_BASIC_FILE_BREAK_CHARACTERS); memset(&coord, 0, sizeof(COORD)); memset(buf, 0, _EL_CONSOLE_BUF_LEN * sizeof(wchar_t)); memset(&irBuffer, 0, sizeof(INPUT_RECORD)); /* allocate buffers */ _el_line_buffer_size = _EL_BUF_LEN + 1; _el_line_buffer = (wchar_t *)malloc(_el_line_buffer_size * sizeof(wchar_t)); if (!_el_mb2w((char *)rl_basic_word_break_characters, &_el_basic_word_break_characters)) { _el_clean_exit(); return NULL; } if (rl_completer_word_break_characters) { if (!_el_mb2w((char *)rl_completer_word_break_characters, &_el_completer_word_break_characters)) { _el_clean_exit(); return NULL; } } if (!(_el_line_buffer)) { _el_clean_exit(); return NULL; } memset(_el_line_buffer, 0, _el_line_buffer_size * sizeof(wchar_t)); rl_attempted_completion_over = 0; _el_print = (wchar_t *)malloc(_el_line_buffer_size * sizeof(wchar_t)); if (!(_el_print)) { _el_clean_exit(); return NULL; } memset(_el_print, 0, _el_line_buffer_size * sizeof(wchar_t)); rl_prompt = _strdup(prompt); if (!(rl_prompt)) { _el_clean_exit(); return NULL; } if (!_el_mb2w((char *)prompt, &_el_prompt)) { _el_clean_exit(); return NULL; } _el_prompt_len = (int)wcslen(_el_prompt); /* get I/O handles for current console */ _el_h_in = GetStdHandle(STD_INPUT_HANDLE); _el_h_out = GetStdHandle(STD_OUTPUT_HANDLE); if ((!(_el_h_in)) || (!(_el_h_out))) { _el_clean_exit(); return NULL; } /* set console modes */ _el_prev_in_cm_saved = GetConsoleMode(_el_h_in, &_el_prev_in_cm); _el_prev_out_cm_saved = GetConsoleMode(_el_h_out, &_el_prev_out_cm); SetConsoleMode(_el_h_in, ENABLE_PROCESSED_INPUT | ENABLE_EXTENDED_FLAGS | ENABLE_INSERT_MODE | ENABLE_QUICK_EDIT_MODE); SetConsoleMode(_el_h_out, ENABLE_PROCESSED_OUTPUT); SetConsoleCtrlHandler((PHANDLER_ROUTINE) _el_signal_handler, TRUE); rl_point = 0; while ((buf[0] != VK_RETURN) && (!_el_ctrl_c_pressed) && _el_line_buffer) { /* get screen buffer info from the current console */ if (!GetConsoleScreenBufferInfo(_el_h_out, &sbInfo)) { _el_clean_exit(); return NULL; } _el_temp_print_size = sbInfo.dwSize.X + 1; if (!(_el_temp_print = realloc(_el_temp_print, _el_temp_print_size * sizeof(wchar_t)))) { _el_clean_exit(); return NULL; } _el_temp_print[0] = _T('\0'); /* compute the current visible console width */ width = sbInfo.srWindow.Right - sbInfo.srWindow.Left + 1; /* if the user has changed the window size update the view */ if (old_width != width) { line_len = (int)wcslen(_el_line_buffer); sbInfo.dwCursorPosition.X = 0; if (old_width) { n = (_el_prompt_len + line_len - 1) / old_width; sbInfo.dwCursorPosition.Y -= n; coord.Y = sbInfo.dwCursorPosition.Y; } if (!SetConsoleCursorPosition(_el_h_out, sbInfo.dwCursorPosition)) { _el_clean_exit(); return NULL; } if (_el_print_string(_el_prompt)) { _el_clean_exit(); return NULL; } if (_el_set_cursor(_el_prompt_len)) { _el_clean_exit(); return NULL; } if (_el_print_string(_el_line_buffer)) { _el_clean_exit(); return NULL; } if (_el_set_cursor(line_len)) { _el_clean_exit(); return NULL; } if (old_width && (old_width < width)) { coord.X = 0; coord.Y += (_el_prompt_len + line_len - 1) / width + 1; FillConsoleOutputCharacter(_el_h_out, _T(' '), sbInfo.dwSize.X * (n + 2), coord, &count); } } old_width = width; /* wait for console events */ if (!PeekConsoleInput(_el_h_in, &irBuffer, 1, &count)) { /* Check we're possibly piped from another program. */ BOOL ret; char *pos, buf[8192]; DWORD to_read = sizeof(buf); /* Can't guarantee Unicode here, we don't control the data passed through the pipe. */ pos = buf; memset(pos, 0, sizeof(buf)); do { ret = ReadFile(_el_h_in, pos, to_read, &count, 0); pos += count; to_read -= count; } while (ret && to_read > 0); if (pos == buf) { _el_clean_exit(); return NULL; } else if (to_read > 0) { /* Tried to fill the buf, but there's nothing anymore. Force finish. */ piped_input_finished = TRUE; } buf[pos - buf] = '\0'; ret_string = _strdup(buf); _el_clean_exit(); return ret_string; } if (count) { if ((irBuffer.EventType == KEY_EVENT) && irBuffer.Event.KeyEvent.bKeyDown) { /* the user pressed a key */ ctrl = (irBuffer.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)); if (irBuffer.Event.KeyEvent.uChar.UnicodeChar == _T('\n')) { if (!ReadConsoleInput(_el_h_in, &irBuffer, 1, &count)) { _el_clean_exit(); return NULL; } buf[0] = VK_RETURN; continue; } if (irBuffer.Event.KeyEvent.uChar.UnicodeChar == _T('\0')) { /* if it is a special key, just remove it from the buffer */ if (!ReadConsoleInput(_el_h_in, &irBuffer, 1, &count)) { _el_clean_exit(); return NULL; } special = irBuffer.Event.KeyEvent.wVirtualKeyCode; /* parse the special key */ switch (special) { /* arrow left, arrow right HOME and END keys */ case VK_LEFT: case VK_RIGHT: case VK_HOME: case VK_END: if (_el_move_cursor(special, ctrl)) { _el_clean_exit(); return NULL; } break; /* arrow up: display previous history element (if any) after recording the current command line */ case VK_UP: if (_el_display_prev_hist()) { _el_clean_exit(); return NULL; } break; /* page up: display the first history element (if any) after recording the current command line */ case VK_PRIOR: if (_el_display_first_hist()) { _el_clean_exit(); return NULL; } break; /* arrow down: display next history element (if any) after recording the current command line */ case VK_DOWN: if (_el_display_next_hist()) { _el_clean_exit(); return NULL; } break; case VK_NEXT: /* page down: display last history element (if any) after recording the current command line */ if (_el_display_last_hist()) { _el_clean_exit(); return NULL; } break; /* delete char */ case VK_DELETE: if (rl_point != wcslen(_el_line_buffer)) { if (_el_delete_char(VK_DELETE, 1)) { _el_clean_exit(); return NULL; } _el_compl_index = 0; compl_pos = -1; } break; } } else { /* if it is a normal key, remove it from the buffer */ memset(buf, 0, _EL_CONSOLE_BUF_LEN * sizeof(wchar_t)); if (!ReadConsole(_el_h_in, buf, 1, &count, NULL)) { _el_clean_exit(); return NULL; } /* then parse it */ switch (buf[0]) { /* backspace */ case VK_BACK: if (rl_point) { _el_compl_index = 0; compl_pos = -1; if (_el_delete_char(VK_BACK, 1)) { _el_clean_exit(); return NULL; } } break; /* TAB: do completion */ case VK_TAB: if ((!array) || (rl_point != compl_pos)) { _el_free_array(array); index = 0; if (_el_text) { free(_el_text); _el_text = NULL; } if (!(_el_text = _el_get_compl_text(&start, &end))) { _el_clean_exit(); return NULL; } if (_el_old_arg) { _el_old_arg[0] = _T('\0'); } if (!_el_w2mb(_el_text, &_el_text_mb)) { _el_clean_exit(); return NULL; } if (!_el_w2mb(_el_line_buffer, &rl_line_buffer)) { _el_clean_exit(); return NULL; } array = (rl_attempted_completion_function ? rl_attempted_completion_function(_el_text_mb, start, end) : rl_completion_matches(_el_text_mb, (rl_completion_entry_function ? rl_completion_entry_function : rl_filename_completion_function))); if (!array) { _el_clean_exit(); return NULL; } } if (!array[index]) { index = 0; } if (array[index]) { if (!_el_mb2w(array[index], &_el_next_compl)) { _el_clean_exit(); return NULL; } len = 0; if (_el_old_arg) { len = (int)wcslen(_el_old_arg); #if 0 fwprintf(stderr, _T("VK_TAB) _el_old_arg = '%s', len = %d\n"), _el_old_arg, len); fflush(stderr); #endif } if (!len) { len = (int)wcslen(_el_text); } if (len) { if (_el_delete_char(VK_BACK, len)) { _el_clean_exit(); return NULL; } } len = (int)wcslen(_el_next_compl); if (!(_el_old_arg = realloc(_el_old_arg, (len + 1) * sizeof(wchar_t)))) { return NULL; } _el_old_arg[len] = _T('\0'); memcpy(_el_old_arg, _el_next_compl, len * sizeof(wchar_t)); line_len = (int)wcslen(_el_line_buffer); if (_el_insert_char(_el_next_compl, len)) { _el_clean_exit(); return NULL; } free(_el_next_compl); _el_next_compl = NULL; compl_pos = ((rl_point && (!wcschr(_el_completer_word_break_characters ? _el_completer_word_break_characters : _el_basic_word_break_characters, _el_line_buffer[rl_point - 1]))) ? rl_point : -1); ++index; } break; /* ENTER: move the cursor to end of line, then return to the caller program */ case VK_RETURN: if (_el_set_cursor((int)wcslen(_el_line_buffer) - rl_point)) { _el_clean_exit(); return NULL; } break; /* delete word */ case 0x17: /* CTRL + W */ if (ctrl) { if (!rl_point) { break; } n = 1; while (((rl_point - n) > 0) && (iswspace(_el_line_buffer[rl_point - n]))) { ++n; } while ((rl_point - n) && (!iswspace(_el_line_buffer[rl_point - n]))) { ++n; } if (rl_point - n) { --n; } _el_compl_index = 0; compl_pos = -1; if (_el_delete_char(VK_BACK, n)) { _el_clean_exit(); return NULL; } break; } /* delete until end of line */ case 0x0B: /* CTRL + K */ if (ctrl) { line_len = (int)wcslen(_el_line_buffer); if (rl_point < line_len) { _el_compl_index = 0; compl_pos = -1; if (_el_delete_char(VK_DELETE, line_len - rl_point)) { _el_clean_exit(); return NULL; } } break; } /* beginning-of-line */ case 0x01: /* CTRL + A */ if (_el_move_cursor(VK_HOME, 0)) { _el_clean_exit(); return NULL; } break; /* end-of-line */ case 0x05: /* CTRL + E */ if (_el_move_cursor(VK_END, 0)) { _el_clean_exit(); return NULL; } break; /* forward-char */ case 0x06: /* CTRL + F */ if (_el_move_cursor(VK_RIGHT, 0)) { _el_clean_exit(); return NULL; } break; /* backward-char */ case 0x02: /* CTRL + B */ if (_el_move_cursor(VK_LEFT, 0)) { _el_clean_exit(); return NULL; } break; /* previous-line */ case 0x10: /* CTRL + P */ if (_el_display_prev_hist()) { _el_clean_exit(); return NULL; } break; /* next-line */ case 0x0E: /* CTRL + N */ if (_el_display_next_hist()) { _el_clean_exit(); return NULL; } break; /* delete char */ case 0x04: /* CTRL + D */ if (rl_point != wcslen(_el_line_buffer)) { if (_el_delete_char(VK_DELETE, 1)) { _el_clean_exit(); return NULL; } _el_compl_index = 0; compl_pos = -1; } break; /* if it is a printable character, print it NOTE: I have later commented out the iswprint() check since for instance it prevents the euro sign from being printed */ default: /*if (iswprint(buf[0])) {*/ _el_compl_index = 0; compl_pos = -1; if (_el_insert_char(buf, 1)) { _el_clean_exit(); return NULL; } /*}*/ } } } /* if it was not a keyboard event, just remove it from buffer */ else if (!ReadConsoleInput(_el_h_in, &irBuffer, 1, &count)) { _el_clean_exit(); return NULL; } } else { /* wait for console input */ WaitForSingleObject(_el_h_in, INFINITE); } } printf("\n"); history_set_pos(history_length()); /* if CTRL+C has been pressed, return an empty string */ if (_el_line_buffer) { if (_el_ctrl_c_pressed) { n = (int)wcslen(_el_line_buffer) - rl_point; if (n) { _el_set_cursor(n); } _el_line_buffer[0] = _T('\0'); } _el_w2mb(_el_line_buffer, &rl_line_buffer); ret_string = _strdup(rl_line_buffer); } _el_clean_exit(); return ret_string; }
bool MovePlayer(CHAR_INFO screenBuffer[], COORD &playerPos) { INPUT_RECORD InputRecord; // Here is our structure to hold the information on the input buffer (what the user does) COORD oldPosition = playerPos; // This stores the old player position so we can erase it when we move. DWORD Events=0; // We create DWORD to be compatible with ReadConsoleInput(). (Holds how many input events took place) HANDLE hInput; // This will be used to query the keyboard bool bPlayerMoved = false; // This holds if the player move or not int bKeyDown = 0; // This tells us if we pressed DOWN a key hInput = GetStdHandle(STD_INPUT_HANDLE); // Here we initialize our input handle "hInput" A HANDLE could be many things so we specify. // Read in the input from the user, storing the information into the InputRecord structure. ReadConsoleInput(hInput, &InputRecord, 1, &Events); // Now we check if there was a keyboard event. // For Windows 95 and 98, we don't need this, but for NT based systems, it handles // the console functions different. In Windows 95 and 98, it only registers a key // when the key is pressed down, where NT OS's register the key up and key down. // This makes the player go 2 moves every time, so we need to make sure we just // move the player when the key is DOWN. We use the bKeyDown variable stored in the // input record, then just make sure it equals "true" when a key is hit. // Notice the "&& bKeyDown" in the following if statement. That says that if the key // was pressed, we only want to enter that if statement if it was a key down press. bKeyDown = InputRecord.Event.KeyEvent.bKeyDown; if(InputRecord.EventType == KEY_EVENT && bKeyDown) { // If the user hits the keyboard: // Check to see if the user hit the RIGHT arrow key if(InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_RIGHT) { if(playerPos.X < (SCREEN_WIDTH - 1) ) // Check to make sure our new position doesn't go outside of our buffer { playerPos.X++; // Increase the player's X value because we are going RIGHT bPlayerMoved = true; // Set the flag to TRUE that the player moved } } // Check to see if we hit the LEFT arrow key else if(InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_LEFT) { if(playerPos.X > 0) // Check to make sure our new position doesn't go outside of our buffer { playerPos.X--; // Decrease the player's X value because we are going LEFT bPlayerMoved = true; // Set the flag to TRUE that the player moved } } // Lets check if we hit the UP arrow: else if(InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_UP) { if(playerPos.Y > 0) // Check to make sure our new position doesn't go outside of our buffer { playerPos.Y--; // Decrease the player's Y value because we are going UP bPlayerMoved = true; // Set the flag to TRUE that the player moved } } // Let's check if we hit the DOWN else if(InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_DOWN) { if(playerPos.Y < (SCREEN_HEIGHT - 1) ) // Check to make sure our new position doesn't go outside of our buffer { playerPos.Y++; // Increase the player's Y value because we are going DOWN bPlayerMoved = true; // Set the flag to TRUE that the player moved } } // If we hit ESCAPE else if(InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) { exit(0); // Quit the program } } // If the player moved if(bPlayerMoved) { // Here we check for collision with a wall. If our new positive is the same X and Y // as a wall, we want to set the characters position back to it's old position. // Otherwise, if it isn't a wall, then we want to erase the old position with a space // If we didn't hit a wall, erase the old position if(screenBuffer[playerPos.X + playerPos.Y * SCREEN_WIDTH].Char.AsciiChar != WALL) { // Erase the old position of the player with a space screenBuffer[oldPosition.X + oldPosition.Y * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[oldPosition.X + oldPosition.Y * SCREEN_WIDTH].Attributes = 0; } else // We hit a wall { // Set the player's position back to it's old position (Hence, we collided) playerPos = oldPosition; } return true; // Return true to say we need to redraw the screen } return false; // We didn't move, so return false }
char *CTextConsoleWin32::GetLine() { while (true) { INPUT_RECORD recs[1024]; unsigned long numread; unsigned long numevents; if (!GetNumberOfConsoleInputEvents(hinput, &numevents)) { if (m_System) { m_System->Errorf("CTextConsoleWin32::GetLine: !GetNumberOfConsoleInputEvents\n"); } return nullptr; } if (numevents <= 0) break; if (!ReadConsoleInput(hinput, recs, ARRAYSIZE(recs), &numread)) { if (m_System) { m_System->Errorf("CTextConsoleWin32::GetLine: !ReadConsoleInput\n"); } return nullptr; } if (numread == 0) return nullptr; for (int i = 0; i < (int)numread; i++) { INPUT_RECORD *pRec = &recs[i]; if (pRec->EventType != KEY_EVENT) continue; if (pRec->Event.KeyEvent.bKeyDown) { // check for cursor keys if (pRec->Event.KeyEvent.wVirtualKeyCode == VK_UP) { ReceiveUpArrow(); } else if (pRec->Event.KeyEvent.wVirtualKeyCode == VK_DOWN) { ReceiveDownArrow(); } else if (pRec->Event.KeyEvent.wVirtualKeyCode == VK_LEFT) { ReceiveLeftArrow(); } else if (pRec->Event.KeyEvent.wVirtualKeyCode == VK_RIGHT) { ReceiveRightArrow(); } else { int nLen; char ch = pRec->Event.KeyEvent.uChar.AsciiChar; switch (ch) { case '\r': // Enter nLen = ReceiveNewline(); if (nLen) { return m_szConsoleText; } break; case '\b': // Backspace ReceiveBackspace(); break; case '\t': // TAB ReceiveTab(); break; default: // dont' accept nonprintable chars if ((ch >= ' ') && (ch <= '~')) { ReceiveStandardChar(ch); } break; } } } } } return nullptr; }
static int getch2_internal(void) { INPUT_RECORD eventbuffer[128]; DWORD retval; int i=0; if(!getch2_status){ // supports e.g. MinGW xterm, unfortunately keys are only received after // enter was pressed. uint8_t c; if (!PeekNamedPipe(in, NULL, 1, &retval, NULL, NULL) || !retval) return -1; ReadFile(in, &c, 1, &retval, NULL); return retval == 1 ? c : -1; } /*check if there are input events*/ if(!GetNumberOfConsoleInputEvents(in,&retval)) { printf("getch2: can't get number of input events: %i\n",GetLastError()); return -1; } if(retval<=0)return -1; /*read all events*/ if(!ReadConsoleInput(in,eventbuffer,128,&retval)) { printf("getch: can't read input events\n"); return -1; } /*filter out keyevents*/ for (i = 0; i < retval; i++) { switch(eventbuffer[i].EventType) { case KEY_EVENT: /*only a pressed key is interresting for us*/ if(eventbuffer[i].Event.KeyEvent.bKeyDown == TRUE) { /*check for special keys*/ switch(eventbuffer[i].Event.KeyEvent.wVirtualKeyCode) { case VK_HOME: return KEY_HOME; case VK_END: return KEY_END; case VK_DELETE: return KEY_DEL; case VK_INSERT: return KEY_INS; case VK_BACK: return KEY_BS; case VK_PRIOR: return KEY_PGUP; case VK_NEXT: return KEY_PGDWN; case VK_RETURN: return KEY_ENTER; case VK_ESCAPE: return KEY_ESC; case VK_LEFT: return KEY_LEFT; case VK_UP: return KEY_UP; case VK_RIGHT: return KEY_RIGHT; case VK_DOWN: return KEY_DOWN; case VK_SHIFT: continue; } /*check for function keys*/ if(0x87 >= eventbuffer[i].Event.KeyEvent.wVirtualKeyCode && eventbuffer[i].Event.KeyEvent.wVirtualKeyCode >= 0x70) return KEY_F + 1 + eventbuffer[i].Event.KeyEvent.wVirtualKeyCode - 0x70; /*only characters should be remaining*/ //printf("getch2: YOU PRESSED \"%c\" \n",eventbuffer[i].Event.KeyEvent.uChar.AsciiChar); return eventbuffer[i].Event.KeyEvent.uChar.AsciiChar; } break; case MOUSE_EVENT: case WINDOW_BUFFER_SIZE_EVENT: case FOCUS_EVENT: case MENU_EVENT: default: //printf("getch2: unsupported event type"); break; } } return -1; }
/* * Read character. */ int ttgetc() { #ifndef __BORLANDC__ DWORD nread; INPUT_RECORD ir; KEY_EVENT_RECORD *ker; unsigned int ch; for (;;) { if (!ReadConsoleInput(hin, &ir, 1, &nread)) return 0; if (ir.EventType != KEY_EVENT) continue; ker = &ir.Event.KeyEvent; if (!ker->bKeyDown) continue; ch = ker->uChar.AsciiChar; if (ch != 0) { if (ch == 0x20 && (ker->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0) { ch = 0; } return ch; } else { ch = ker->wVirtualScanCode; int shifted = ker->dwControlKeyState & SHIFT_PRESSED; if (ch >= 0x3b && ch <= 0x44) { /* Function keys. Test for shifted state. */ if (shifted) return (ch - 0x3b + 0x54) | 0x100; else return ch | 0x100; } else if ((ch >= 0x47 && ch <= 0x53) || (ch >= 0x57 && ch <= 0x58)) { /* Direction keys, or F11-F12. */ return ch | 0x100; } } } #else int ch; if ((ch = getch()) == 0) /* extended key */ { if ((ch = getch()) == 3) /* null? */ return 0; /* convert to 0 */ else return (ch + 0x100); /* flag this as extended key */ } else return (ch); /* normal key */ #endif }
int main(VOID) { DWORD cNumRead, fdwMode, i; INPUT_RECORD irInBuf[128]; int counter = 0; Combo *combo = new Combo(5, { "1990", "1991", "1992", "1993" }); //combo->draw(); Panel panel(30, 30); panel.AddiControl(*combo, 2, 3); panel.draw(); // Get the standard input handle. hStdin = GetStdHandle(STD_INPUT_HANDLE); if (hStdin == INVALID_HANDLE_VALUE) combo->ErrorExit("GetStdHandle", hStdin, fdwSaveOldMode); hStdout = GetStdHandle(STD_OUTPUT_HANDLE); if (!GetConsoleMode(hStdin, &fdwSaveOldMode)) combo->ErrorExit("GetConsoleMode", hStdin, fdwSaveOldMode); // Enable the window and mouse input events. fdwMode = ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT; if (!SetConsoleMode(hStdin, fdwMode)) combo->ErrorExit("SetConsoleMode", hStdin, fdwSaveOldMode); while (counter++ != EOF) { // Wait for the events. if (!ReadConsoleInput( hStdin, // input buffer handle irInBuf, // buffer to read into 128, // size of read buffer &cNumRead)) // number of records read combo->ErrorExit("ReadConsoleInput", hStdin, fdwSaveOldMode); // Dispatch the events to the appropriate handler. for (i = 0; i < cNumRead; i++) { switch (irInBuf[i].EventType) { case KEY_EVENT: // keyboard input combo->KeyEventProc(irInBuf[i].Event.KeyEvent, hStdout); break; case MOUSE_EVENT: // mouse input combo->MouseEventProc(irInBuf[i].Event.MouseEvent, hStdout); break; case WINDOW_BUFFER_SIZE_EVENT: // scrn buf. resizing combo->ResizeEventProc(irInBuf[i].Event.WindowBufferSizeEvent); break; default: //combo->ErrorExit("Unknown event type", hStdin, fdwSaveOldMode); break; } } } // Restore input mode on exit. SetConsoleMode(hStdin, fdwSaveOldMode); return 0; }
/* ================== CON_ConsoleInput ================== */ char *CON_ConsoleInput (void) { INPUT_RECORD buff[MAXCMDLINE]; DWORD count = 0, events = 0; WORD key = 0; int i; int newlinepos = -1; if (!GetNumberOfConsoleInputEvents(qconsole_hin, &events)) return NULL; if (events < 1) return NULL; // if we have overflowed, start dropping oldest input events if (events >= MAXCMDLINE) { ReadConsoleInput(qconsole_hin, buff, 1, &events); return NULL; } if (!ReadConsoleInput(qconsole_hin, buff, events, &count)) return NULL; FlushConsoleInputBuffer(qconsole_hin); for (i = 0; i < count; i++) { if (buff[i].EventType != KEY_EVENT) continue; if (!buff[i].Event.KeyEvent.bKeyDown) continue; key = buff[i].Event.KeyEvent.wVirtualKeyCode; if (key == VK_RETURN) { newlinepos = i; break; } else if (key == VK_UP) { CON_HistPrev(); break; } else if (key == VK_DOWN) { CON_HistNext(); break; } else if (key == VK_TAB) { // command completion field_t f; Field_Clear(&f); Q_strlcpy(f.buffer, qconsole_line, sizeof(f.buffer)); Field_AutoComplete(&f); Q_strlcpy(qconsole_line, f.buffer, sizeof(qconsole_line)); qconsole_linelen = strlen(qconsole_line); break; } if (qconsole_linelen < sizeof(qconsole_line) - 1) { char c = buff[i].Event.KeyEvent.uChar.AsciiChar; if (key == VK_BACK) { int pos = (qconsole_linelen > 0) ? qconsole_linelen - 1 : 0; qconsole_line[pos] = '\0'; qconsole_linelen = pos; } else if (c) { qconsole_line[qconsole_linelen++] = c; qconsole_line[qconsole_linelen] = '\0'; } } } if (newlinepos < 0) { CON_Show(); return NULL; } if (!qconsole_linelen) { CON_Show(); Com_Printf("\n"); return NULL; } qconsole_linelen = 0; CON_Show(); CON_HistAdd(); Com_Printf("%s\n", qconsole_line); return qconsole_line; }
int do_everything(int argc, LPCWSTR argv[]) { HRESULT hr = S_OK; // parse command line CPrefs prefs(argc, argv, hr); if (FAILED(hr)) { printf("CPrefs::CPrefs constructor failed: hr = 0x%08x\n", hr); return __LINE__; } if (S_FALSE == hr) { // nothing to do return 0; } // create a "silence has started playing" event HANDLE hStartedEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (NULL == hStartedEvent) { printf("CreateEvent failed: last error is %u\n", GetLastError()); return __LINE__; } // create a "stop playing silence now" event HANDLE hStopEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (NULL == hStopEvent) { printf("CreateEvent failed: last error is %u\n", GetLastError()); CloseHandle(hStartedEvent); return __LINE__; } // create arguments for silence-playing thread PlaySilenceThreadFunctionArguments threadArgs; threadArgs.hr = E_UNEXPECTED; // thread will overwrite this threadArgs.hStartedEvent = hStartedEvent; threadArgs.hStopEvent = hStopEvent; threadArgs.pMMDevice = prefs.m_pMMDevice; HANDLE hThread = CreateThread( NULL, 0, PlaySilenceThreadFunction, &threadArgs, 0, NULL ); if (NULL == hThread) { printf("CreateThread failed: last error is %u\n", GetLastError()); CloseHandle(hStopEvent); CloseHandle(hStartedEvent); return __LINE__; } // wait for either silence to start or the thread to end HANDLE waitArray[2] = { hStartedEvent, hThread }; DWORD dwWaitResult; dwWaitResult = WaitForMultipleObjects( _countof(waitArray), waitArray, FALSE, INFINITE ); if (WAIT_OBJECT_0 + 1 == dwWaitResult) { printf("Thread aborted before starting to play silence: hr = 0x%08x\n", threadArgs.hr); CloseHandle(hStartedEvent); CloseHandle(hThread); CloseHandle(hStopEvent); return __LINE__; } if (WAIT_OBJECT_0 != dwWaitResult) { printf("Unexpected WaitForMultipleObjects return value %u: last error is %u\n", dwWaitResult, GetLastError()); CloseHandle(hStartedEvent); CloseHandle(hThread); CloseHandle(hStopEvent); return __LINE__; } CloseHandle(hStartedEvent); HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE); if (INVALID_HANDLE_VALUE == hStdIn) { printf("GetStdHandle returned INVALID_HANDLE_VALUE: last error is %u\n", GetLastError()); SetEvent(hStopEvent); WaitForSingleObject(hThread, INFINITE); CloseHandle(hStartedEvent); CloseHandle(hThread); CloseHandle(hStopEvent); return __LINE__; } printf("Press Enter to quit...\n"); // wait for the thread to terminate early // or for the user to press (and release) Enter HANDLE rhHandles[2] = { hThread, hStdIn }; bool bKeepWaiting = true; while (bKeepWaiting) { dwWaitResult = WaitForMultipleObjects(2, rhHandles, FALSE, INFINITE); switch (dwWaitResult) { case WAIT_OBJECT_0: // hThread printf("The thread terminated early - something bad happened\n"); bKeepWaiting = false; break; case WAIT_OBJECT_0 + 1: // hStdIn // see if any of them was an Enter key-up event INPUT_RECORD rInput[128]; DWORD nEvents; if (!ReadConsoleInput(hStdIn, rInput, _countof(rInput), &nEvents)) { printf("ReadConsoleInput failed: last error is %u\n", GetLastError()); SetEvent(hStopEvent); WaitForSingleObject(hThread, INFINITE); bKeepWaiting = false; } else { for (DWORD i = 0; i < nEvents; i++) { if ( KEY_EVENT == rInput[i].EventType && VK_RETURN == rInput[i].Event.KeyEvent.wVirtualKeyCode && !rInput[i].Event.KeyEvent.bKeyDown ) { printf("Aborting playback...\n"); SetEvent(hStopEvent); WaitForSingleObject(hThread, INFINITE); bKeepWaiting = false; break; } } // if none of them were Enter key-up events, // continue waiting } break; default: printf("WaitForMultipleObjects returned unexpected value 0x%08x\n", dwWaitResult); SetEvent(hStopEvent); WaitForSingleObject(hThread, INFINITE); bKeepWaiting = false; break; } } DWORD exitCode; if (!GetExitCodeThread(hThread, &exitCode)) { printf("GetExitCodeThread failed: last error is %u\n", GetLastError()); CloseHandle(hThread); CloseHandle(hStopEvent); return __LINE__; } if (0 != exitCode) { printf("Silence thread exit code is %u; expected 0\n", exitCode); CloseHandle(hThread); CloseHandle(hStopEvent); return __LINE__; } if (S_OK != threadArgs.hr) { printf("Thread HRESULT is 0x%08x\n", threadArgs.hr); CloseHandle(hThread); CloseHandle(hStopEvent); return __LINE__; } CloseHandle(hThread); CloseHandle(hStopEvent); return 0; }
int main() { HANDLE hFile = CreateFile(TEXT("lyric.txt"), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); ReadFile(hFile, lyrics, sizeof(lyrics), &length, NULL); length = lstrlen(lyrics); CloseHandle(hFile); DWORD i, j; tags[count].milliseconds = 0; tags[count].begin = tags[count].end = lyrics; tags[count].length = 0; tags[count].position.X = tags[count].position.Y = 0; ++count; for(i=0, j=0; i<length; ++i) if( schema[j](lyrics[i]) ) { if(j==9) { tags[count].milliseconds = (lyrics[i-8] - '0') * 10 + (lyrics[i-7] - '0'); tags[count].milliseconds = tags[count].milliseconds * 6 + (lyrics[i-5] - '0'); tags[count].milliseconds = tags[count].milliseconds * 10 + (lyrics[i-4] - '0'); tags[count].milliseconds = tags[count].milliseconds * 10 + (lyrics[i-2] - '0'); tags[count].milliseconds = tags[count].milliseconds * 10 + (lyrics[i-1] - '0'); tags[count].milliseconds *= 10; tags[count].begin = lyrics + i + 1; ++count; j=0; } else ++j; } else j=0; for(i=1; i<count-1; ++i) { tags[i].end = tags[i+1].begin - 10; tags[i].length = tags[i].end - tags[i].begin; } tags[i].end = lyrics + length; tags[i].length = tags[i].end - tags[i].begin; tags[count].milliseconds = tags[count-1].milliseconds + 1000; tags[count].begin = tags[count].end = lyrics + length; tags[count].length = 0; tags[count].position.X = tags[count].position.Y = 0; ++count; HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); // GetCurrentConsoleFontEx(hStdout, FALSE, lpConsoleCurrentFontEx); // SetCurrentConsoleFontEx(hStdout, FALSE, lpConsoleCurrentFontEx); SetConsoleCursorInfo(hStdout, &CURSOR_INVISIBLE); SetConsoleTextAttribute(hStdout, FOREGROUND_NORMAL); for(i=0; i<count; ++i) { CONSOLE_SCREEN_BUFFER_INFO info; GetConsoleScreenBufferInfo(hStdout, &info); tags[i].position = info.dwCursorPosition; WriteConsole(hStdout, tags[i].begin, tags[i].end-tags[i].begin, NULL, NULL); } HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); SetConsoleMode(hStdin, 0); INPUT_RECORD inputRecord; DWORD numbleRead, numbleWritten; DWORD currentTagIndex = 0; Timer timer; for(;;) { INT millisecondsToWait = INFINITE; if (timer.getRate() > 0) { millisecondsToWait = ( tags[currentTagIndex+1].milliseconds - timer.getTime() ) / timer.getRate() - REDUNDANCY; if (millisecondsToWait < 0) millisecondsToWait = 0; } if (timer.getRate() < 0) { millisecondsToWait = ( tags[currentTagIndex].milliseconds - timer.getTime() ) / timer.getRate() - REDUNDANCY; if (millisecondsToWait < 0) millisecondsToWait = 0; } if (WaitForSingleObject(hStdin, millisecondsToWait) == WAIT_OBJECT_0) { ReadConsoleInput(hStdin, &inputRecord, 1, &numbleRead); if (inputRecord.EventType == KEY_EVENT) { if (inputRecord.Event.KeyEvent.bKeyDown == TRUE) { if (inputRecord.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) { SetConsoleCursorPosition(hStdout, tags[count-2].position); break; } if (timer.getRate() == 1 && inputRecord.Event.KeyEvent.wVirtualKeyCode == 'A') timer.setRate( -FAST_RUNNING_RATE ); if (timer.getRate() == 1 && inputRecord.Event.KeyEvent.wVirtualKeyCode == 'D') timer.setRate( +FAST_RUNNING_RATE ); } else { if (timer.getRate() < 0 && inputRecord.Event.KeyEvent.wVirtualKeyCode == 'A') timer.setRate( 1 ); if (timer.getRate() > 0 && inputRecord.Event.KeyEvent.wVirtualKeyCode == 'D') timer.setRate( 1 ); } } else if (inputRecord.EventType == FOCUS_EVENT) { if (timer.getRate() != 1 && inputRecord.Event.FocusEvent.bSetFocus == FALSE) timer.setRate( 1 ); } } while (currentTagIndex+1 < count && tags[currentTagIndex+1].milliseconds <= timer.getTime()) { FillConsoleOutputAttribute(hStdout, FOREGROUND_NORMAL, tags[currentTagIndex].length, tags[currentTagIndex].position, &numbleWritten); ++currentTagIndex; FillConsoleOutputAttribute(hStdout, FOREGROUND_HIGHLIGHT, tags[currentTagIndex].length, tags[currentTagIndex].position, &numbleWritten); SetConsoleCursorPosition(hStdout, tags[currentTagIndex].position); } while (currentTagIndex > 0 && tags[currentTagIndex].milliseconds > timer.getTime()) { FillConsoleOutputAttribute(hStdout, FOREGROUND_NORMAL, tags[currentTagIndex].length, tags[currentTagIndex].position, &numbleWritten); --currentTagIndex; FillConsoleOutputAttribute(hStdout, FOREGROUND_HIGHLIGHT, tags[currentTagIndex].length, tags[currentTagIndex].position, &numbleWritten); SetConsoleCursorPosition(hStdout, tags[currentTagIndex].position); } if (currentTagIndex == count - 1) { currentTagIndex = 0; timer.setTime( 0 ); } } return 0; }
int main(int argc, char* argv[]) { CheckLogsFolder(); CoInitializeEx(NULL, COINIT_MULTITHREADED); CTradePublish TradePub; CQuotePublish QuotePub; CVolatilityPublish VolaPub; try { /*ISubManagerPtr pSubMng; pSubMng.CreateInstance(CLSID_MsgManager); if(pSubMng == NULL) throw _com_error(E_FAIL); ISymbolObjectPtr pSymbol; pSymbol.CreateInstance(CLSID_SymbolObject); if(pSymbol == NULL) throw _com_error(E_FAIL); pSymbol->Set(enStStock,L"MSFT",L"NASD",L"USD"); pSubMng->raw_SubVola(pSymbol); pSubMng->raw_SubQuote(pSymbol); pSubMng->raw_SubTradeUpdate(); */QuotePub.Initialize(); QuotePub.Start(); TradePub.Initialize(); TradePub.Start(); VolaPub.Initialize(); VolaPub.Start(); HANDLE hStdin; DWORD cNumRead, fdwMode, fdwSaveOldMode; INPUT_RECORD irInBuf[2]; // Get the standard input handle. hStdin = GetStdHandle(STD_INPUT_HANDLE); if (hStdin == INVALID_HANDLE_VALUE) throw -1; // Save the current input mode, to be restored on exit. if (! GetConsoleMode(hStdin, &fdwSaveOldMode) ) throw -1; // Enable the window input events. fdwMode = ENABLE_WINDOW_INPUT; if (! SetConsoleMode(hStdin, fdwMode) ) throw -1; // Loop to read and handle the input events. while (1) { // Wait for the events. if (! ReadConsoleInput( hStdin, // input buffer handle irInBuf, // buffer to read into 2, // size of read buffer &cNumRead) ) // number of records read throw -1; // Dispatch the events to the appropriate handler. if(irInBuf[0].EventType == KEY_EVENT ) { if(irInBuf[0].Event.KeyEvent.dwControlKeyState & LEFT_CTRL_PRESSED) { if(irInBuf[0].Event.KeyEvent.wVirtualKeyCode == 67) break; } } } } catch(...) { } VolaPub.Stop(); VolaPub.Uninitialize(); TradePub.Stop(); TradePub.Uninitialize(); QuotePub.Stop(); QuotePub.Uninitialize(); CoUninitialize(); return 0; }