#include "pdcwin.h"
#include <tchar.h>
#include <stdint.h>
#include <assert.h>
static short *color_pair_indices = (short *)NULL;
COLORREF *pdc_rgbs = (COLORREF *)NULL;
static int menu_shown = 1;
static int min_lines = 25, max_lines = 25;
static int min_cols = 80, max_cols = 80;
#if defined( CHTYPE_LONG) && CHTYPE_LONG >= 2 && defined( PDC_WIDE)
#define USING_COMBINING_CHARACTER_SCHEME
int PDC_expand_combined_characters( const cchar_t c, cchar_t *added);
#endif
#ifdef _MSC_VER
#define INLINE static
#else
#define INLINE static inline
#endif
static int keep_size_within_bounds( int *lines, int *cols);
INLINE int set_default_sizes_from_registry( const int n_cols, const int n_rows,
const int xloc, const int yloc, const int menu_shown);
void PDC_transform_line_given_hdc( const HDC hdc, const int lineno,
int x, int len, const chtype *srcp);
#define N_COLORS 256
#ifdef A_OVERLINE
#define A_ALL_LINES (A_UNDERLINE | A_LEFTLINE | A_RIGHTLINE | A_OVERLINE | A_STRIKEOUT)
#else
#define A_ALL_LINES (A_UNDERLINE | A_LEFTLINE | A_RIGHTLINE)
#endif
#ifndef PDC_MAX_MOUSE_BUTTONS
#define PDC_MAX_MOUSE_BUTTONS 3
#endif
#define VERTICAL_WHEEL_EVENT PDC_MAX_MOUSE_BUTTONS
#define HORIZONTAL_WHEEL_EVENT (PDC_MAX_MOUSE_BUTTONS + 1)
unsigned long pdc_key_modifiers = 0L;
int PDC_show_ctrl_alts = 0;
bool PDC_bDone = FALSE;
static HWND originally_focussed_window;
int debug_printf( const char *format, ...)
{
static bool debugging = TRUE;
if( debugging)
{
const char *output_filename = getenv( "PDC_DEBUG");
if( !output_filename)
debugging = FALSE;
else
{
FILE *ofile = fopen( output_filename, "a");
if( ofile)
{
va_list argptr;
va_start( argptr, format);
vfprintf( ofile, format, argptr);
va_end( argptr);
fclose( ofile);
}
else
{
printf( "Opening '%s' failed\n", output_filename);
exit( 0);
debugging = FALSE;
}
}
}
return( 0);
}
HWND PDC_hWnd;
static int PDC_argc = 0;
static char **PDC_argv = NULL;
static void final_cleanup( void)
{
debug_printf( "final_cleanup: SP = %p\n", SP);
if (SP)
{
RECT rect;
GetWindowRect( PDC_hWnd, &rect);
set_default_sizes_from_registry( SP->cols, SP->lines,
rect.left, rect.top, menu_shown);
}
PDC_LOG(( "final_cleanup: freeing fonts\n"));
PDC_transform_line( 0, 0, 0, NULL);
if( originally_focussed_window)
SetForegroundWindow( originally_focussed_window);
if( PDC_argc)
{
int i;
for( i = 0; i < PDC_argc; i++)
free( PDC_argv[i]);
free( PDC_argv);
PDC_argc = 0;
PDC_argv = NULL;
}
#ifdef USING_COMBINING_CHARACTER_SCHEME
PDC_expand_combined_characters( 0, NULL);
#endif
debug_printf( "reset foreground window\n");
}
void PDC_scr_close(void)
{
PDC_LOG(("PDC_scr_close() - called\n"));
final_cleanup( );
PDC_bDone = TRUE;
}
void PDC_scr_free(void)
{
if (SP)
free(SP);
SP = (SCREEN *)NULL;
if (color_pair_indices)
free(color_pair_indices);
color_pair_indices = (short *)NULL;
if (pdc_rgbs)
free(pdc_rgbs);
pdc_rgbs = (COLORREF *)NULL;
}
int PDC_choose_a_new_font( void);
void PDC_add_clipboard_to_key_queue( void);
#define KEY_QUEUE_SIZE 30
static int PDC_shutdown_key[PDC_MAX_FUNCTION_KEYS] = { 0, 22, CTL_EQUAL, CTL_MINUS,
CTL_COMMA };
int PDC_n_rows, PDC_n_cols;
int PDC_cxChar, PDC_cyChar, PDC_key_queue_low = 0, PDC_key_queue_high = 0;
int PDC_key_queue[KEY_QUEUE_SIZE];
bool PDC_allow_numpad_unicode = TRUE;
static int numpad_unicode_value = 0;
static void adjust_font_size( const int font_size_change);
static void add_key_to_queue( const int new_key)
{
const int new_idx = ((PDC_key_queue_high + 1) % KEY_QUEUE_SIZE);
static int unicode_radix = 10;
if( PDC_allow_numpad_unicode)
{
int digit = -1;
if( new_key >= ALT_PAD0 && new_key <= ALT_PAD9)
digit = new_key - ALT_PAD0;
if( unicode_radix == 16 && new_key >= ALT_0 && new_key <= ALT_9)
digit = new_key - ALT_0;
if( unicode_radix == 16 && new_key >= ALT_A && new_key <= ALT_F)
digit = new_key - ALT_A + 10;
if( digit >= 0)
{
numpad_unicode_value = numpad_unicode_value * unicode_radix + digit;
return;
}
if( new_key == ALT_PADPLUS)
{
unicode_radix = 16;
return;
}
}
unicode_radix = 10;
if( new_key && new_key == PDC_shutdown_key[FUNCTION_KEY_PASTE])
PDC_add_clipboard_to_key_queue( );
else if( new_key && new_key == PDC_shutdown_key[FUNCTION_KEY_ABORT])
exit( -1);
else if( new_key && new_key == PDC_shutdown_key[FUNCTION_KEY_ENLARGE_FONT])
adjust_font_size( 1);
else if( new_key && new_key == PDC_shutdown_key[FUNCTION_KEY_SHRINK_FONT])
adjust_font_size( -1);
else if( new_key && new_key == PDC_shutdown_key[FUNCTION_KEY_CHOOSE_FONT])
{
if( PDC_choose_a_new_font( ))
adjust_font_size( 0);
}
else if( new_idx != PDC_key_queue_low)
{
PDC_key_queue[PDC_key_queue_high] = new_key;
PDC_key_queue_high = new_idx;
}
}
typedef struct
{
unsigned short normal;
unsigned short shift;
unsigned short control;
unsigned short alt;
unsigned short extended;
} KPTAB;
static const KPTAB kptab[] =
{
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{CTL_PAUSE, 'a', 'b', 'c', 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{0x08, 0x08, 0x7F, ALT_BKSP, 0 },
{0x09, KEY_BTAB, CTL_TAB, ALT_TAB, 999 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{KEY_B2, 0x35, CTL_PAD5, ALT_PAD5, 0 },
{0x0D, 0x0D, CTL_ENTER, ALT_ENTER, 1 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{KEY_PAUSE, KEY_SPAUSE,CTL_PAUSE, 0, 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{0x1B, 0x1B, 0x1B, ALT_ESC, 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{0x20, 0x20, 0x20, 0x20, 0 },
{KEY_A3, 0x39, CTL_PAD9, ALT_PAD9, 3 },
{KEY_C3, 0x33, CTL_PAD3, ALT_PAD3, 4 },
{KEY_C1, 0x31, CTL_PAD1, ALT_PAD1, 5 },
{KEY_A1, 0x37, CTL_PAD7, ALT_PAD7, 6 },
{KEY_B1, 0x34, CTL_PAD4, ALT_PAD4, 7 },
{KEY_A2, 0x38, CTL_PAD8, ALT_PAD8, 8 },
{KEY_B3, 0x36, CTL_PAD6, ALT_PAD6, 9 },
{KEY_C2, 0x32, CTL_PAD2, ALT_PAD2, 10 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{KEY_PRINTSCREEN, 0, 0, ALT_PRINTSCREEN, 0 },
{PAD0, 0x30, CTL_PAD0, ALT_PAD0, 11 },
{PADSTOP, 0x2E, CTL_PADSTOP, ALT_PADSTOP,12 },
{0, 0, 0, 0, 0 },
{0x30, 0x29, CTL_0, ALT_0, 0 },
{0x31, 0x21, CTL_1, ALT_1, 0 },
{0x32, 0x40, CTL_2, ALT_2, 0 },
{0x33, 0x23, CTL_3, ALT_3, 0 },
{0x34, 0x24, CTL_4, ALT_4, 0 },
{0x35, 0x25, CTL_5, ALT_5, 0 },
{0x36, 0x5E, CTL_6, ALT_6, 0 },
{0x37, 0x26, CTL_7, ALT_7, 0 },
{0x38, 0x2A, CTL_8, ALT_8, 0 },
{0x39, 0x28, CTL_9, ALT_9, 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{0x61, 0x41, 0x01, ALT_A, 0 },
{0x62, 0x42, 0x02, ALT_B, 0 },
{0x63, 0x43, 0x03, ALT_C, 0 },
{0x64, 0x44, 0x04, ALT_D, 0 },
{0x65, 0x45, 0x05, ALT_E, 0 },
{0x66, 0x46, 0x06, ALT_F, 0 },
{0x67, 0x47, 0x07, ALT_G, 0 },
{0x68, 0x48, 0x08, ALT_H, 0 },
{0x69, 0x49, 0x09, ALT_I, 0 },
{0x6A, 0x4A, 0x0A, ALT_J, 0 },
{0x6B, 0x4B, 0x0B, ALT_K, 0 },
{0x6C, 0x4C, 0x0C, ALT_L, 0 },
{0x6D, 0x4D, 0x0D, ALT_M, 0 },
{0x6E, 0x4E, 0x0E, ALT_N, 0 },
{0x6F, 0x4F, 0x0F, ALT_O, 0 },
{0x70, 0x50, 0x10, ALT_P, 0 },
{0x71, 0x51, 0x11, ALT_Q, 0 },
{0x72, 0x52, 0x12, ALT_R, 0 },
{0x73, 0x53, 0x13, ALT_S, 0 },
{0x74, 0x54, 0x14, ALT_T, 0 },
{0x75, 0x55, 0x15, ALT_U, 0 },
{0x76, 0x56, 0x16, ALT_V, 0 },
{0x77, 0x57, 0x17, ALT_W, 0 },
{0x78, 0x58, 0x18, ALT_X, 0 },
{0x79, 0x59, 0x19, ALT_Y, 0 },
{0x7A, 0x5A, 0x1A, ALT_Z, 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{KEY_APPS, KEY_SAPPS, CTL_APPS, ALT_APPS, 13 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{0x30, 0, CTL_PAD0, ALT_PAD0, 0 },
{0x31, 0, CTL_PAD1, ALT_PAD1, 0 },
{0x32, 0, CTL_PAD2, ALT_PAD2, 0 },
{0x33, 0, CTL_PAD3, ALT_PAD3, 0 },
{0x34, 0, CTL_PAD4, ALT_PAD4, 0 },
{0x35, 0, CTL_PAD5, ALT_PAD5, 0 },
{0x36, 0, CTL_PAD6, ALT_PAD6, 0 },
{0x37, 0, CTL_PAD7, ALT_PAD7, 0 },
{0x38, 0, CTL_PAD8, ALT_PAD8, 0 },
{0x39, 0, CTL_PAD9, ALT_PAD9, 0 },
{PADSTAR, SHF_PADSTAR,CTL_PADSTAR, ALT_PADSTAR,999 },
{PADPLUS, SHF_PADPLUS,CTL_PADPLUS, ALT_PADPLUS,999 },
{0, 0, 0, 0, 0 },
{PADMINUS, SHF_PADMINUS,CTL_PADMINUS,ALT_PADMINUS,999},
{0x2E, 0, CTL_PADSTOP, ALT_PADSTOP,0 },
{PADSLASH, SHF_PADSLASH,CTL_PADSLASH,ALT_PADSLASH,2 },
{KEY_F(1), KEY_F(13), KEY_F(25), KEY_F(37), 0 },
{KEY_F(2), KEY_F(14), KEY_F(26), KEY_F(38), 0 },
{KEY_F(3), KEY_F(15), KEY_F(27), KEY_F(39), 0 },
{KEY_F(4), KEY_F(16), KEY_F(28), KEY_F(40), 0 },
{KEY_F(5), KEY_F(17), KEY_F(29), KEY_F(41), 0 },
{KEY_F(6), KEY_F(18), KEY_F(30), KEY_F(42), 0 },
{KEY_F(7), KEY_F(19), KEY_F(31), KEY_F(43), 0 },
{KEY_F(8), KEY_F(20), KEY_F(32), KEY_F(44), 0 },
{KEY_F(9), KEY_F(21), KEY_F(33), KEY_F(45), 0 },
{KEY_F(10), KEY_F(22), KEY_F(34), KEY_F(46), 0 },
{KEY_F(11), KEY_F(23), KEY_F(35), KEY_F(47), 0 },
{KEY_F(12), KEY_F(24), KEY_F(36), KEY_F(48), 0 },
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{KEY_SCROLLLOCK, 0, 0, ALT_SCROLLLOCK, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 14},
{0, 0, 0, 0, 15},
{0, 0, 0, 0, 16},
{0, 0, 0, 0, 17},
{0, 0, 0, 0, 18},
{0, 0, 0, 0, 19},
{0, 0, 0, 0, 20},
{0, 0, 0, 0, 21},
{0, 0, 0, 0, 22},
{0, 0, 0, 0, 23},
{0, 0, 0, 0, 24},
{0, 0, 0, 0, 25},
{0, 0, 0, 0, 26},
{0, 0, 0, 0, 27},
{0, 0, 0, 0, 28},
{0, 0, 0, 0, 29},
{0, 0, 0, 0, 30},
{0, 0, 0, 0, 31},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{';', ':', CTL_SEMICOLON, ALT_SEMICOLON, 0},
{'=', '+', CTL_EQUAL, ALT_EQUAL, 0},
{',', '<', CTL_COMMA, ALT_COMMA, 0},
{'-', '_', CTL_MINUS, ALT_MINUS, 0},
{'.', '>', CTL_STOP, ALT_STOP, 0},
{'/', '?', CTL_FSLASH, ALT_FSLASH, 0},
{'`', '~', CTL_BQUOTE, ALT_BQUOTE, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0x5B, 0x7B, 0x1B, ALT_LBRACKET,0 },
{0x5C, 0x7C, 0x1C, ALT_BSLASH, 0 },
{0x5D, 0x7D, 0x1D, ALT_RBRACKET,0 },
{'\'', '"', 0x27, ALT_FQUOTE, 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 },
{0, 0, 0, 0, 0 }
};
static const KPTAB ext_kptab[] =
{
{0, 0, 0, 0, },
{PADENTER, SHF_PADENTER, CTL_PADENTER, ALT_PADENTER},
{PADSLASH, SHF_PADSLASH, CTL_PADSLASH, ALT_PADSLASH},
{KEY_PPAGE, KEY_SPREVIOUS, CTL_PGUP, ALT_PGUP },
{KEY_NPAGE, KEY_SNEXT, CTL_PGDN, ALT_PGDN },
{KEY_END, KEY_SEND, CTL_END, ALT_END },
{KEY_HOME, KEY_SHOME, CTL_HOME, ALT_HOME },
{KEY_LEFT, KEY_SLEFT, CTL_LEFT, ALT_LEFT },
{KEY_UP, KEY_SUP, CTL_UP, ALT_UP },
{KEY_RIGHT, KEY_SRIGHT, CTL_RIGHT, ALT_RIGHT },
{KEY_DOWN, KEY_SDOWN, CTL_DOWN, ALT_DOWN },
{KEY_IC, KEY_SIC, CTL_INS, ALT_INS },
{KEY_DC, KEY_SDC, CTL_DEL, ALT_DEL },
{KEY_APPS, KEY_SAPPS , CTL_APPS, ALT_APPS },
{KEY_BROWSER_BACK, KEY_SBROWSER_BACK, KEY_CBROWSER_BACK, KEY_ABROWSER_BACK, },
{KEY_BROWSER_FWD, KEY_SBROWSER_FWD, KEY_CBROWSER_FWD, KEY_ABROWSER_FWD, },
{KEY_BROWSER_REF, KEY_SBROWSER_REF, KEY_CBROWSER_REF, KEY_ABROWSER_REF, },
{KEY_BROWSER_STOP, KEY_SBROWSER_STOP, KEY_CBROWSER_STOP, KEY_ABROWSER_STOP, },
{KEY_SEARCH, KEY_SSEARCH, KEY_CSEARCH, KEY_ASEARCH, },
{KEY_FAVORITES, KEY_SFAVORITES, KEY_CFAVORITES, KEY_AFAVORITES, },
{KEY_BROWSER_HOME, KEY_SBROWSER_HOME, KEY_CBROWSER_HOME, KEY_ABROWSER_HOME, },
{KEY_VOLUME_MUTE, KEY_SVOLUME_MUTE, KEY_CVOLUME_MUTE, KEY_AVOLUME_MUTE, },
{KEY_VOLUME_DOWN, KEY_SVOLUME_DOWN, KEY_CVOLUME_DOWN, KEY_AVOLUME_DOWN, },
{KEY_VOLUME_UP, KEY_SVOLUME_UP, KEY_CVOLUME_UP, KEY_AVOLUME_UP, },
{KEY_NEXT_TRACK, KEY_SNEXT_TRACK, KEY_CNEXT_TRACK, KEY_ANEXT_TRACK, },
{KEY_PREV_TRACK, KEY_SPREV_TRACK, KEY_CPREV_TRACK, KEY_APREV_TRACK, },
{KEY_MEDIA_STOP, KEY_SMEDIA_STOP, KEY_CMEDIA_STOP, KEY_AMEDIA_STOP, },
{KEY_PLAY_PAUSE, KEY_SPLAY_PAUSE, KEY_CPLAY_PAUSE, KEY_APLAY_PAUSE, },
{KEY_LAUNCH_MAIL, KEY_SLAUNCH_MAIL, KEY_CLAUNCH_MAIL, KEY_ALAUNCH_MAIL, },
{KEY_MEDIA_SELECT, KEY_SMEDIA_SELECT, KEY_CMEDIA_SELECT, KEY_AMEDIA_SELECT, },
{KEY_LAUNCH_APP1, KEY_SLAUNCH_APP1, KEY_CLAUNCH_APP1, KEY_ALAUNCH_APP1, },
{KEY_LAUNCH_APP2, KEY_SLAUNCH_APP2, KEY_CLAUNCH_APP2, KEY_ALAUNCH_APP2, },
};
HFONT PDC_get_font_handle( const int is_bold);
static int set_mouse( const int button_index, const int button_state,
const LPARAM lParam)
{
int i, n_key_mouse_to_add = 1;
POINT pt;
pt.x = LOWORD( lParam);
pt.y = HIWORD( lParam);
if( button_index == -1)
n_key_mouse_to_add = 1;
else
{
memset(&pdc_mouse_status, 0, sizeof(MOUSE_STATUS));
if( button_index < PDC_MAX_MOUSE_BUTTONS)
{
if( button_index < 3)
{
pdc_mouse_status.button[button_index] = (short)button_state;
pdc_mouse_status.changes = (1 << button_index);
}
else
{
pdc_mouse_status.xbutton[button_index - 3] = (short)button_state;
pdc_mouse_status.changes = (0x40 << button_index);
}
}
else
{
static int mouse_wheel_vertical_loc = 0;
static int mouse_wheel_horizontal_loc = 0;
const int mouse_wheel_sensitivity = 120;
n_key_mouse_to_add = 0;
if( button_index == VERTICAL_WHEEL_EVENT)
{
mouse_wheel_vertical_loc += button_state;
while( mouse_wheel_vertical_loc > mouse_wheel_sensitivity / 2)
{
n_key_mouse_to_add++;
mouse_wheel_vertical_loc -= mouse_wheel_sensitivity;
pdc_mouse_status.changes |= PDC_MOUSE_WHEEL_UP;
}
while( mouse_wheel_vertical_loc < -mouse_wheel_sensitivity / 2)
{
n_key_mouse_to_add++;
mouse_wheel_vertical_loc += mouse_wheel_sensitivity;
pdc_mouse_status.changes |= PDC_MOUSE_WHEEL_DOWN;
}
}
else
{
mouse_wheel_horizontal_loc += button_state;
while( mouse_wheel_horizontal_loc > mouse_wheel_sensitivity / 2)
{
n_key_mouse_to_add++;
mouse_wheel_horizontal_loc -= mouse_wheel_sensitivity;
pdc_mouse_status.changes |= PDC_MOUSE_WHEEL_RIGHT;
}
while( mouse_wheel_horizontal_loc < -mouse_wheel_sensitivity / 2)
{
n_key_mouse_to_add++;
mouse_wheel_horizontal_loc += mouse_wheel_sensitivity;
pdc_mouse_status.changes |= PDC_MOUSE_WHEEL_LEFT;
}
}
pt.x = -PDC_cxChar;
pt.y = -PDC_cyChar;
}
}
pdc_mouse_status.x = pt.x / PDC_cxChar;
pdc_mouse_status.y = pt.y / PDC_cyChar;
{
int i, button_flags = 0;
if( GetKeyState( VK_MENU) & 0x8000)
button_flags |= PDC_BUTTON_ALT;
if( GetKeyState( VK_SHIFT) & 0x8000)
button_flags |= PDC_BUTTON_SHIFT;
if( GetKeyState( VK_CONTROL) & 0x8000)
button_flags |= PDC_BUTTON_CONTROL;
for (i = 0; i < 3; i++)
pdc_mouse_status.button[i] |= button_flags;
for (i = 0; i < PDC_N_EXTENDED_MOUSE_BUTTONS; i++)
pdc_mouse_status.xbutton[i] |= button_flags;
}
i = PDC_key_queue_low;
while( i != PDC_key_queue_high)
{
if( PDC_key_queue[i] == KEY_MOUSE)
{
debug_printf( "Mouse key already in queue\n");
return( 0);
}
i = (i + 1) % KEY_QUEUE_SIZE;
}
if( pdc_mouse_status.x >= PDC_n_cols || pdc_mouse_status.y >= PDC_n_rows)
n_key_mouse_to_add = 0;
while( n_key_mouse_to_add--)
add_key_to_queue( KEY_MOUSE);
return( 0);
}
#ifndef WM_MOUSEWHEEL
#define WM_MOUSEWHEEL 0x020A
#endif
#ifndef WM_MOUSEHWHEEL
#define WM_MOUSEHWHEEL 0x020E
#endif
#ifndef WM_XBUTTONDOWN
#define WM_XBUTTONDOWN 0x020B
#define WM_XBUTTONUP 0x020C
#define MK_XBUTTON1 0x0020
#define MK_XBUTTON2 0x0040
#endif
#ifdef USE_FALLBACK_FONT
extern GLYPHSET *PDC_unicode_range_data;
#endif
int PDC_blink_state = 0;
#define TIMER_ID_FOR_BLINKING 0x2000
static void get_character_sizes( const HWND hwnd,
int *xchar_size, int *ychar_size)
{
HFONT hFont = PDC_get_font_handle( 0);
HFONT prev_font;
HDC hdc = GetDC (hwnd) ;
TEXTMETRIC tm ;
#ifdef USE_FALLBACK_FONT
DWORD size;
#endif
prev_font = SelectObject (hdc, hFont);
GetTextMetrics (hdc, &tm) ;
#ifdef USE_FALLBACK_FONT
assert( !PDC_unicode_range_data);
size = GetFontUnicodeRanges( hdc, NULL);
PDC_unicode_range_data = (GLYPHSET *)calloc( 1, size);
PDC_unicode_range_data->cbThis = size;
size = GetFontUnicodeRanges( hdc, PDC_unicode_range_data);
#endif
SelectObject( hdc, prev_font);
ReleaseDC (hwnd, hdc) ;
DeleteObject( hFont);
*xchar_size = tm.tmAveCharWidth ;
*ychar_size = tm.tmHeight;
}
INLINE void sort_out_rect( RECT *rect)
{
int temp;
if( rect->left > rect->right)
{
temp = rect->right;
rect->right = rect->left;
rect->left = temp;
}
if( rect->top > rect->bottom)
{
temp = rect->bottom;
rect->bottom = rect->top;
rect->top = temp;
}
}
static int rectangle_from_chars_to_pixels( RECT *rect)
{
int rval = 1;
if( rect->right == rect->left && rect->top == rect->bottom)
rval = 0;
sort_out_rect( rect);
if( rect->top < 0)
rval = 0;
rect->right++;
rect->bottom++;
rect->left *= PDC_cxChar;
rect->right *= PDC_cxChar;
rect->top *= PDC_cyChar;
rect->bottom *= PDC_cyChar;
return( rval);
}
static int PDC_selecting_rectangle = 1;
int PDC_find_ends_of_selected_text( const int line,
const RECT *rect, int *x)
{
int rval = 0, i;
if( (rect->top - line) * (rect->bottom - line) <= 0
&& (rect->top != rect->bottom || rect->left != rect->right))
{
if( PDC_selecting_rectangle || rect->top == rect->bottom)
{
x[0] = min( rect->right, rect->left);
x[1] = max( rect->right, rect->left);
rval = 1;
}
else if( rect->top <= line && line <= rect->bottom)
{
x[0] = (line == rect->top ? rect->left : 0);
x[1] = (line == rect->bottom ? rect->right : SP->cols - 1);
rval = 1;
}
else if( rect->top >= line && line >= rect->bottom)
{
x[0] = (line == rect->bottom ? rect->right : 0);
x[1] = (line == rect->top ? rect->left : SP->cols - 1);
rval = 1;
}
}
if( rval)
for( i = 0; i < 2; i++)
if( x[i] > SP->cols - 1)
x[i] = SP->cols - 1;
return( rval);
}
INLINE void show_mouse_rect( const HWND hwnd, RECT before, RECT after)
{
if( before.top > -1 || after.top > -1)
if( memcmp( &after, &before, sizeof( RECT)))
{
const HDC hdc = GetDC( hwnd) ;
if( PDC_selecting_rectangle)
{
const int show_before = rectangle_from_chars_to_pixels( &before);
const int show_after = rectangle_from_chars_to_pixels( &after);
if( show_before && show_after)
{
RECT temp;
if( before.top < after.top)
{
temp = before; before = after; after = temp;
}
if( before.top < after.bottom && after.right > before.left
&& before.right > after.left)
{
const int tval = min( after.bottom, before.bottom);
temp = after;
temp.bottom = before.top;
InvertRect( hdc, &temp);
temp.top = temp.bottom;
temp.bottom = tval;
temp.right = max( after.right, before.right);
temp.left = min( after.right, before.right);
InvertRect( hdc, &temp);
temp.right = max( after.left, before.left);
temp.left = min( after.left, before.left);
InvertRect( hdc, &temp);
temp = (after.bottom > before.bottom ? after : before);
temp.top = tval;
InvertRect( hdc, &temp);
}
}
else if( show_before)
InvertRect( hdc, &before);
else if( show_after)
InvertRect( hdc, &after);
}
else
{
int line;
for( line = 0; line < SP->lines; line++)
{
int x[4], n_rects = 0, i;
n_rects = PDC_find_ends_of_selected_text( line, &before, x);
n_rects += PDC_find_ends_of_selected_text( line, &after, x + n_rects * 2);
if( n_rects == 2)
if( x[0] == x[2] && x[1] == x[3])
n_rects = 0;
for( i = 0; i < n_rects; i++)
{
RECT trect;
trect.left = x[i + i];
trect.right = x[i + i + 1];
trect.top = line;
trect.bottom = line;
rectangle_from_chars_to_pixels( &trect);
InvertRect( hdc, &trect);
}
}
}
ReleaseDC( hwnd, hdc) ;
}
}
#ifdef __CYGWIN__
#ifdef PDC_WIDE
static void my_wsplitpath( const wchar_t *path, wchar_t *drive,
wchar_t *dir, wchar_t *fname, wchar_t *ext)
{
size_t i, loc = 0;
assert( path);
assert( fname);
if( path[0] && path[1] == ':')
{
if( drive)
{
drive[0] = path[0];
drive[1] = ':';
drive[2] = '\0';
}
path += 2;
}
else if( drive)
*drive = '\0';
for( i = 0; path[i]; i++)
if( path[i] == '/' || path[i] == '\\')
loc = i + 1;
if( dir)
{
memcpy( dir, path, loc * sizeof( wchar_t));
dir[loc] = '\0';
}
if( loc)
path += loc;
loc = 0;
while( path[loc] && path[loc] != '.')
loc++;
if( fname)
{
memcpy( fname, path, loc * sizeof( wchar_t));
fname[loc] = '\0';
}
if( ext)
wcscpy( ext, path + loc);
}
#endif
static void my_splitpath( const char *path, char *drive,
char *dir, char *fname, char *ext)
{
size_t i, loc = 0;
assert( path);
assert( fname);
if( path[0] && path[1] == ':')
{
if( drive)
{
drive[0] = path[0];
drive[1] = ':';
drive[2] = '\0';
}
path += 2;
}
else if( drive)
*drive = '\0';
for( i = 0; path[i]; i++)
if( path[i] == '/' || path[i] == '\\')
loc = i + 1;
if( dir)
{
memcpy( dir, path, loc * sizeof( char));
dir[loc] = '\0';
}
if( loc)
path += loc;
loc = 0;
while( path[loc] && path[loc] != '.')
loc++;
if( fname)
{
memcpy( fname, path, loc * sizeof( char));
fname[loc] = '\0';
}
if( ext)
strcpy( ext, path + loc);
}
#else
#define my_splitpath _splitpath
#define my_wsplitpath _wsplitpath
#define GOT_ARGV_ARGC
#endif
#ifdef UNICODE
#define my_stprintf wsprintf
#define my_tcslen wcslen
#ifdef __CYGWIN__
#define my_tcslwr
#elif defined _MSC_VER
#define my_tcslwr _wcslwr
#else
#define my_tcslwr wcslwr
#endif
#define my_tcscat wcscat
#define my_tcscpy wcscpy
#define my_stscanf swscanf
#else
#define my_stprintf sprintf
#define my_tcslen strlen
#define my_tcslwr strlwr
#ifdef _MSC_VER
#define strlwr _strlwr
#endif
#define my_tcscat strcat
#define my_tcscpy strcpy
#define my_stscanf sscanf
#endif
static void get_app_name( TCHAR *buff, const bool include_args)
{
int i;
#ifdef GOT_ARGV_ARGC
int argc = (PDC_argc ? PDC_argc : __argc);
char **argv = (PDC_argc ? PDC_argv : __argv);
#else
int argc = PDC_argc;
char **argv = PDC_argv;
#endif
#ifdef PDC_WIDE
#ifdef GOT_ARGV_ARGC
if( __wargv)
{
my_wsplitpath( __wargv[0], NULL, NULL, buff, NULL);
if( include_args)
for( i = 1; i < __argc; i++)
{
wcscat( buff, L" ");
wcscat( buff, __wargv[i]);
}
}
else
#endif
if( argv)
{
char tbuff[MAX_PATH];
my_splitpath( argv[0], NULL, NULL, tbuff, NULL);
if( include_args)
for( i = 1; i < argc; i++)
{
strcat( tbuff, " ");
strcat( tbuff, argv[i]);
}
mbstowcs( buff, tbuff, strlen( tbuff) + 1);
}
else
{
wchar_t *tptr;
my_wsplitpath( GetCommandLine( ), NULL, NULL, buff, NULL);
my_tcslwr( buff + 1);
tptr = wcsstr( buff, L".exe\"");
if( tptr)
{
if( include_args)
memmove( tptr, tptr + 5, wcslen( tptr + 4) * sizeof( wchar_t));
else
*tptr = '\0';
}
}
#else
if( argv)
{
my_splitpath( argv[0], NULL, NULL, buff, NULL);
debug_printf( "Path: %s; exe: %s\n", argv[0], buff);
if( include_args)
for( i = 1; i < argc; i++)
{
strcat( buff, " ");
strcat( buff, argv[i]);
}
}
else
{
char *tptr;
my_splitpath( GetCommandLine( ), NULL, NULL, buff, NULL);
strlwr( buff + 1);
tptr = strstr( buff, ".exe\"");
if( tptr)
{
if( include_args)
memmove( tptr, tptr + 5, strlen( tptr + 4));
else
*tptr = '\0';
}
}
#endif
my_tcslwr( buff + 1);
}
INLINE HICON get_app_icon( )
{
#ifdef PDC_WIDE
wchar_t filename[MAX_PATH];
#else
char filename[MAX_PATH];
#endif
HICON icon = NULL;
if ( GetModuleFileName( NULL, filename, sizeof(filename) ) != 0 )
icon = ExtractIcon( 0, filename, 0 );
return icon;
}
extern TCHAR PDC_font_name[];
INLINE int set_default_sizes_from_registry( const int n_cols, const int n_rows,
const int xloc, const int yloc, const int menu_shown)
{
DWORD is_new_key;
HKEY hNewKey;
long rval = RegCreateKeyEx( HKEY_CURRENT_USER, _T( "SOFTWARE\\PDCurses"),
0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
0, &hNewKey, &is_new_key);
if( rval == ERROR_SUCCESS)
{
TCHAR buff[180];
TCHAR key_name[MAX_PATH];
extern int PDC_font_size;
if( IsZoomed( PDC_hWnd))
my_stprintf( buff,
_T( "-1x-1,%d,0,0,%d"), PDC_font_size, menu_shown);
else
my_stprintf( buff,
_T( "%dx%d,%d,%d,%d,%d"), n_cols, n_rows, PDC_font_size,
xloc, yloc, menu_shown);
my_stprintf( buff + my_tcslen( buff),
_T(";%d,%d,%d,%d:"),
min_lines, max_lines,
min_cols, max_cols);
my_tcscat( buff, PDC_font_name);
get_app_name( key_name, FALSE);
rval = RegSetValueEx( hNewKey, key_name, 0, REG_SZ,
(BYTE *)buff, (DWORD)( my_tcslen( buff) * sizeof( TCHAR)));
RegCloseKey( hNewKey);
}
debug_printf( "Size: %d %d; %d\n", n_cols, n_rows, rval);
return( rval != ERROR_SUCCESS);
}
static void fix_up_edges( const HDC hdc, const RECT *rect)
{
const int x = PDC_n_cols * PDC_cxChar;
const int y = PDC_n_rows * PDC_cyChar;
if( rect->right >= x || rect->bottom >= y)
{
const HBRUSH hOldBrush =
SelectObject( hdc, GetStockObject( BLACK_BRUSH));
SelectObject( hdc, GetStockObject( NULL_PEN));
if( rect->right >= x)
Rectangle( hdc, x, rect->top, rect->right + 1, rect->bottom + 1);
if( rect->bottom >= y)
Rectangle( hdc, rect->left, y, rect->right + 1, rect->bottom + 1);
SelectObject( hdc, hOldBrush);
}
}
static void adjust_font_size( const int font_size_change)
{
extern int PDC_font_size;
PDC_font_size += font_size_change;
if( PDC_font_size < 2)
PDC_font_size = 2;
PDC_transform_line( 0, 0, 0, NULL);
get_character_sizes( PDC_hWnd, &PDC_cxChar, &PDC_cyChar);
if( IsZoomed( PDC_hWnd))
{
RECT client_rect;
HDC hdc;
GetClientRect( PDC_hWnd, &client_rect);
PDC_n_rows = client_rect.bottom / PDC_cyChar;
PDC_n_cols = client_rect.right / PDC_cxChar;
keep_size_within_bounds( &PDC_n_rows, &PDC_n_cols);
PDC_resize_screen( PDC_n_rows, PDC_n_cols);
add_key_to_queue( KEY_RESIZE);
SP->resized = TRUE;
hdc = GetDC (PDC_hWnd) ;
GetClientRect( PDC_hWnd, &client_rect);
fix_up_edges( hdc, &client_rect);
ReleaseDC( PDC_hWnd, hdc) ;
}
else
{
PDC_resize_screen( PDC_n_rows, PDC_n_cols);
InvalidateRect( PDC_hWnd, NULL, FALSE);
}
}
RECT PDC_mouse_rect = { -1, -1, -1, -1 };
int PDC_setclipboard_raw( const char *contents, long length,
const bool translate_multibyte_to_wide_char);
INLINE void HandleBlockCopy( void)
{
int i, j, len, x[2];
TCHAR *buff, *tptr;
for( i = len = 0; i < SP->lines; i++)
if( PDC_find_ends_of_selected_text( i, &PDC_mouse_rect, x))
len += x[1] - x[0] + 3;
buff = tptr = (TCHAR *)malloc( (len + 1) * sizeof( TCHAR));
for( i = len = 0; i < SP->lines; i++)
if( PDC_find_ends_of_selected_text( i, &PDC_mouse_rect, x))
{
const chtype *cptr = curscr->_y[i];
for( j = 0; j < x[1] - x[0] + 1; j++)
tptr[j] = (TCHAR)cptr[j + x[0]];
while( j > 0 && tptr[j - 1] == ' ')
j--;
tptr += j;
*tptr++ = (TCHAR)13;
*tptr++ = (TCHAR)10;
}
if( tptr != buff)
{
tptr[-2] = '\0';
PDC_setclipboard_raw( (char *)buff, (long)( tptr - buff), FALSE);
}
free( buff);
}
#define WM_ENLARGE_FONT (WM_USER + 1)
#define WM_SHRINK_FONT (WM_USER + 2)
#define WM_MARK_AND_COPY (WM_USER + 3)
#define WM_TOGGLE_MENU (WM_USER + 4)
#define WM_EXIT_GRACELESSLY (WM_USER + 5)
#define WM_CHOOSE_FONT (WM_USER + 6)
static int add_resize_key = 1;
void PDC_set_resize_limits( const int new_min_lines, const int new_max_lines,
const int new_min_cols, const int new_max_cols)
{
min_lines = max( new_min_lines, 2);
max_lines = max( new_max_lines, min_lines);
min_cols = max( new_min_cols, 2);
max_cols = max( new_max_cols, min_cols);
}
static void adjust_window_size( int *xpixels, int *ypixels, int window_style,
const int menu_shown)
{
RECT rect;
rect.left = rect.top = 0;
rect.right = *xpixels;
rect.bottom = *ypixels;
AdjustWindowRect( &rect, window_style, menu_shown);
*xpixels = rect.right - rect.left;
*ypixels = rect.bottom - rect.top;
}
static int keep_size_within_bounds( int *lines, int *cols)
{
int rval = 0;
if( *lines < min_lines)
{
*lines = min_lines;
rval = 1;
}
else if( *lines > max_lines)
{
*lines = max_lines;
rval = 2;
}
if( *cols < min_cols)
{
*cols = min_cols;
rval |= 4;
}
else if( *cols > max_cols)
{
*cols = max_cols;
rval |= 8;
}
return( rval);
}
INLINE int get_default_sizes_from_registry( int *n_cols, int *n_rows,
int *xloc, int *yloc, int *menu_shown)
{
TCHAR data[100];
DWORD size_out = sizeof( data);
HKEY hKey = 0;
long rval = RegOpenKeyEx( HKEY_CURRENT_USER, _T( "SOFTWARE\\PDCurses"),
0, KEY_READ, &hKey);
if( !hKey)
return( 1);
if( rval == ERROR_SUCCESS)
{
TCHAR key_name[MAX_PATH];
get_app_name( key_name, FALSE);
rval = RegQueryValueEx( hKey, key_name,
NULL, NULL, (BYTE *)data, &size_out);
if( rval == ERROR_SUCCESS)
{
extern int PDC_font_size;
int x = -1, y = -1, bytes_read = 0;
my_stscanf( data, _T( "%dx%d,%d,%d,%d,%d;%d,%d,%d,%d:%n"),
&x, &y, &PDC_font_size,
xloc, yloc, menu_shown,
&min_lines, &max_lines,
&min_cols, &max_cols,
&bytes_read);
if( bytes_read > 0 && data[bytes_read - 1] == ':')
my_tcscpy( PDC_font_name, data + bytes_read);
if( n_cols)
*n_cols = x;
if( n_rows)
*n_rows = y;
if( *n_cols > 0 && *n_rows > 0)
keep_size_within_bounds( n_rows, n_cols);
}
RegCloseKey( hKey);
}
if( rval != ERROR_SUCCESS)
debug_printf( "get_default_sizes_from_registry error: %d\n", rval);
return( rval != ERROR_SUCCESS);
}
INLINE void HandleSizing( WPARAM wParam, LPARAM lParam )
{
RECT *rect = (RECT *)lParam;
RECT window_rect, client_rect;
int hadd, vadd, width, height;
int n_rows, n_cols;
int rounded_width, rounded_height;
GetWindowRect( PDC_hWnd, &window_rect);
GetClientRect( PDC_hWnd, &client_rect);
hadd = (window_rect.right - window_rect.left) - client_rect.right;
vadd = (window_rect.bottom - window_rect.top) - client_rect.bottom;
width = rect->right - rect->left - hadd;
height = rect->bottom - rect->top - vadd;
n_cols = (width + PDC_cxChar / 2) / PDC_cxChar;
n_rows = (height + PDC_cyChar / 2) / PDC_cyChar;
keep_size_within_bounds( &n_rows, &n_cols);
rounded_width = hadd + n_cols * PDC_cxChar;
rounded_height = vadd + n_rows * PDC_cyChar;
if( wParam == WMSZ_BOTTOM || wParam == WMSZ_BOTTOMLEFT
|| wParam == WMSZ_BOTTOMRIGHT)
rect->bottom = rect->top + rounded_height;
if( wParam == WMSZ_TOP || wParam == WMSZ_TOPLEFT
|| wParam == WMSZ_TOPRIGHT)
rect->top = rect->bottom - rounded_height;
if( wParam == WMSZ_RIGHT || wParam == WMSZ_BOTTOMRIGHT
|| wParam == WMSZ_TOPRIGHT)
rect->right = rect->left + rounded_width;
if( wParam == WMSZ_LEFT || wParam == WMSZ_BOTTOMLEFT
|| wParam == WMSZ_TOPLEFT)
rect->left = rect->right - rounded_width;
}
typedef const char *(CDECL *wine_version_func)(void);
static wine_version_func wine_version;
static void HandleSize( const WPARAM wParam, const LPARAM lParam)
{
static WPARAM prev_wParam = (WPARAM)-99;
const unsigned n_xpixels = LOWORD (lParam);
const unsigned n_ypixels = HIWORD (lParam);
unsigned new_n_rows, new_n_cols;
debug_printf( "WM_SIZE: wParam %x %d %d %d\n", (unsigned)wParam,
n_xpixels, n_ypixels, SP->resized);
if( wParam == SIZE_MINIMIZED )
{
prev_wParam = SIZE_MINIMIZED;
return;
}
new_n_rows = n_ypixels / PDC_cyChar;
new_n_cols = n_xpixels / PDC_cxChar;
debug_printf( "Size was %d x %d; will be %d x %d\n",
PDC_n_rows, PDC_n_cols, new_n_rows, new_n_cols);
SP->resized = FALSE;
if( PDC_n_rows != (int)new_n_rows || PDC_n_cols != (int)new_n_cols)
{
PDC_n_cols = new_n_cols;
PDC_n_rows = new_n_rows;
debug_printf( "prev_wParam = %d; add_resize_key = %d\n",
(int)prev_wParam, add_resize_key);
if( prev_wParam != (WPARAM)-99 && add_resize_key)
{
add_key_to_queue( KEY_RESIZE);
SP->resized = TRUE;
}
}
else if( wine_version)
return;
add_resize_key = 1;
if( wParam == SIZE_RESTORED &&
( n_xpixels % PDC_cxChar || n_ypixels % PDC_cyChar))
{
int new_xpixels = PDC_cxChar * PDC_n_cols;
int new_ypixels = PDC_cyChar * PDC_n_rows;
adjust_window_size( &new_xpixels, &new_ypixels,
GetWindowLong( PDC_hWnd, GWL_STYLE), menu_shown);
debug_printf( "Irregular size\n");
SetWindowPos( PDC_hWnd, 0, 0, 0,
new_xpixels, new_ypixels,
SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW);
}
prev_wParam = wParam;
}
static void HandleMouseMove( WPARAM wParam, LPARAM lParam,
int* ptr_modified_key_to_return )
{
const int mouse_x = LOWORD( lParam) / PDC_cxChar;
const int mouse_y = HIWORD( lParam) / PDC_cyChar;
static int prev_mouse_x, prev_mouse_y;
if( mouse_x != prev_mouse_x || mouse_y != prev_mouse_y)
{
int report_event = 0;
prev_mouse_x = mouse_x;
prev_mouse_y = mouse_y;
if( wParam & MK_LBUTTON)
{
PDC_mouse_rect.left = mouse_x;
PDC_mouse_rect.top = mouse_y;
if( SP->_trap_mbe & BUTTON1_MOVED)
report_event |= PDC_MOUSE_MOVED | 1;
}
if( wParam & MK_MBUTTON)
if( SP->_trap_mbe & BUTTON2_MOVED)
report_event |= PDC_MOUSE_MOVED | 2;
if( wParam & MK_RBUTTON)
if( SP->_trap_mbe & BUTTON3_MOVED)
report_event |= PDC_MOUSE_MOVED | 4;
#ifdef CANT_DO_THINGS_THIS_WAY
if( wParam & MK_XBUTTON1)
if( SP->_trap_mbe & BUTTON4_MOVED)
report_event |= PDC_MOUSE_MOVED | 8;
if( wParam & MK_XBUTTON2)
if( SP->_trap_mbe & BUTTON5_MOVED)
report_event |= PDC_MOUSE_MOVED | 16;
#endif
if( !report_event)
if( SP->_trap_mbe & REPORT_MOUSE_POSITION)
report_event = PDC_MOUSE_POSITION;
if( report_event)
{
int i;
pdc_mouse_status.changes = report_event;
for( i = 0; i < 3; i++)
{
pdc_mouse_status.button[i] = (((report_event >> i) & 1) ?
BUTTON_MOVED : 0);
}
*ptr_modified_key_to_return = 0;
set_mouse( -1, 0, lParam );
}
}
}
static void HandlePaint( HWND hwnd )
{
PAINTSTRUCT ps;
HDC hdc;
RECT rect;
GetUpdateRect( hwnd, &rect, FALSE);
hdc = BeginPaint( hwnd, &ps);
fix_up_edges( hdc, &rect);
if( curscr && curscr->_y)
{
int i, x1, n_chars;
x1 = rect.left / PDC_cxChar;
n_chars = rect.right / PDC_cxChar - x1 + 1;
if( n_chars > SP->cols - x1)
n_chars = SP->cols - x1;
if( n_chars > 0)
for( i = rect.top / PDC_cyChar; i <= rect.bottom / PDC_cyChar; i++)
if( i < SP->lines && curscr->_y[i])
PDC_transform_line_given_hdc( hdc, i, x1,
n_chars, curscr->_y[i] + x1);
}
EndPaint( hwnd, &ps );
}
static bool key_already_handled = FALSE;
static void HandleSyskeyDown( const WPARAM wParam, const LPARAM lParam,
int *ptr_modified_key_to_return )
{
const int shift_pressed = (GetKeyState( VK_SHIFT) & 0x8000);
const int ctrl_pressed = (GetKeyState( VK_CONTROL) & 0x8000);
const int alt_pressed = (GetKeyState( VK_MENU) & 0x8000);
const int extended = ((lParam & 0x01000000) != 0);
const int repeated = (int)( lParam >> 30) & 1;
const KPTAB *kptr = kptab + wParam;
int key = 0;
if( !repeated)
*ptr_modified_key_to_return = 0;
if( SP->return_key_modifiers && !repeated)
{
if( wParam == VK_SHIFT)
{
if( GetKeyState( VK_LSHIFT) & 0x8000)
*ptr_modified_key_to_return = KEY_SHIFT_L;
else if( GetKeyState( VK_RSHIFT) & 0x8000)
*ptr_modified_key_to_return = KEY_SHIFT_R;
else if(( HIWORD( lParam) & 0xff) == 0x36)
*ptr_modified_key_to_return = KEY_SHIFT_R;
else
*ptr_modified_key_to_return = KEY_SHIFT_L;
}
if( wParam == VK_CONTROL)
*ptr_modified_key_to_return =
(extended ? KEY_CONTROL_R : KEY_CONTROL_L);
if( wParam == VK_MENU)
*ptr_modified_key_to_return =
(extended ? KEY_ALT_R : KEY_ALT_L);
}
if( !key)
{
if( extended && kptr->extended != 999)
kptr = ext_kptab + kptr->extended;
if( alt_pressed)
key = kptr->alt;
else if( ctrl_pressed)
key = kptr->control;
else if( shift_pressed)
key = kptr->shift;
else
key = kptr->normal;
}
if( key >= KEY_MIN && key <= KEY_MAX)
if( !ctrl_pressed || !alt_pressed || PDC_show_ctrl_alts)
{
add_key_to_queue( key);
if( wParam == VK_MULTIPLY || wParam == VK_DIVIDE
|| wParam == VK_ADD || wParam == VK_SUBTRACT
|| wParam == VK_RETURN)
key_already_handled = TRUE;
}
pdc_key_modifiers = 0;
if (SP->save_key_modifiers)
{
if( alt_pressed)
pdc_key_modifiers |= PDC_KEY_MODIFIER_ALT;
if( shift_pressed)
pdc_key_modifiers |= PDC_KEY_MODIFIER_SHIFT;
if( ctrl_pressed)
pdc_key_modifiers |= PDC_KEY_MODIFIER_CONTROL;
if( GetKeyState( VK_NUMLOCK) & 1)
pdc_key_modifiers |= PDC_KEY_MODIFIER_NUMLOCK;
}
}
static void HandleTimer( const WPARAM wParam )
{
int i;
extern int PDC_really_blinking;
static int previously_really_blinking = 0;
static int prev_line_color = -1;
chtype attr_to_seek = 0;
if( prev_line_color != SP->line_color)
attr_to_seek = A_ALL_LINES;
if( PDC_really_blinking || previously_really_blinking)
attr_to_seek |= A_BLINK;
prev_line_color = SP->line_color;
previously_really_blinking = PDC_really_blinking;
PDC_blink_state ^= 1;
if( attr_to_seek)
{
for( i = 0; i < SP->lines; i++)
{
if( curscr->_y[i])
{
int j = 0, n_chars;
chtype *line = curscr->_y[i];
while( j < SP->cols && !(*line & attr_to_seek))
{
j++;
line++;
}
n_chars = SP->cols - j;
while( n_chars && !(line[n_chars - 1] & attr_to_seek))
{
n_chars--;
}
if( n_chars)
PDC_transform_line( i, j, n_chars, line);
}
}
}
if( SP->cursrow >=SP->lines || SP->curscol >= SP->cols
|| SP->cursrow < 0 || SP->curscol < 0
|| !curscr->_y || !curscr->_y[SP->cursrow])
debug_printf( "Cursor off-screen: %d %d, %d %d\n",
SP->cursrow, SP->curscol, SP->lines, SP->cols);
else if( PDC_CURSOR_IS_BLINKING)
PDC_transform_line( SP->cursrow, SP->curscol, 1,
curscr->_y[SP->cursrow] + SP->curscol);
}
static HMENU set_menu( void)
{
const HMENU hMenu = CreateMenu( );
#ifdef PDC_WIDE
AppendMenu( hMenu, MF_STRING, WM_CHOOSE_FONT, L"Font");
AppendMenu( hMenu, MF_STRING, WM_PASTE, L"Paste");
#else
AppendMenu( hMenu, MF_STRING, WM_CHOOSE_FONT, "Font");
AppendMenu( hMenu, MF_STRING, WM_PASTE, "Paste");
#endif
return( hMenu);
}
INLINE void HandleMenuToggle( bool *ptr_ignore_resize)
{
const bool is_zoomed = IsZoomed( PDC_hWnd);
HMENU hMenu;
menu_shown ^= 1;
hMenu = GetSystemMenu( PDC_hWnd, FALSE);
CheckMenuItem( hMenu, WM_TOGGLE_MENU, MF_BYCOMMAND
| (menu_shown ? MF_CHECKED : MF_UNCHECKED));
if( !is_zoomed)
*ptr_ignore_resize = TRUE;
if( !menu_shown)
{
hMenu = GetMenu( PDC_hWnd);
DestroyMenu( hMenu);
hMenu = CreateMenu( );
SetMenu( PDC_hWnd, hMenu);
}
else
{
SetMenu( PDC_hWnd, set_menu( ));
}
*ptr_ignore_resize = FALSE;
if( !is_zoomed)
{
PDC_resize_screen( PDC_n_rows, PDC_n_cols );
}
InvalidateRect( PDC_hWnd, NULL, FALSE);
}
INLINE uint64_t milliseconds_since_1970( void)
{
FILETIME ft;
const uint64_t jd_1601 = 2305813;
const uint64_t jd_1970 = 2440587;
const uint64_t ten_million = 10000000;
const uint64_t diff = (jd_1970 - jd_1601) * ten_million * 86400;
uint64_t decimicroseconds_since_1970;
GetSystemTimeAsFileTime( &ft);
decimicroseconds_since_1970 = ((uint64_t)ft.dwLowDateTime |
((uint64_t)ft.dwHighDateTime << 32)) - diff;
return( decimicroseconds_since_1970 / 10000);
}
#if defined(_WIN32) && defined(__GNUC__)
#define ALIGN_STACK __attribute__((force_align_arg_pointer))
#else
#define ALIGN_STACK
#endif
static LRESULT ALIGN_STACK CALLBACK WndProc (const HWND hwnd,
const UINT message,
const WPARAM wParam,
const LPARAM lParam)
{
int button_down = -1, button_up = -1;
static int mouse_buttons_pressed = 0;
static LPARAM mouse_lParam;
static uint64_t last_click_time[PDC_MAX_MOUSE_BUTTONS];
static int modified_key_to_return = 0;
const RECT before_rect = PDC_mouse_rect;
static bool ignore_resize = FALSE;
PDC_hWnd = hwnd;
if( !hwnd)
debug_printf( "Null hWnd: msg %u, wParam %x, lParam %lx\n",
message, wParam, lParam);
switch (message)
{
case WM_SIZING:
HandleSizing( wParam, lParam );
return( TRUE );
case WM_SIZE:
if( ignore_resize == FALSE)
HandleSize( wParam, lParam);
return 0 ;
case WM_MOUSEWHEEL:
debug_printf( "Mouse wheel: %x %lx\n", wParam, lParam);
modified_key_to_return = 0;
set_mouse( VERTICAL_WHEEL_EVENT, (short)( HIWORD(wParam)), lParam);
break;
case WM_MOUSEHWHEEL:
debug_printf( "Mouse horiz wheel: %x %lx\n", wParam, lParam);
modified_key_to_return = 0;
set_mouse( HORIZONTAL_WHEEL_EVENT, (short)( HIWORD(wParam)), lParam);
break;
case WM_MOUSEMOVE:
HandleMouseMove( wParam, lParam, &modified_key_to_return );
break;
case WM_LBUTTONDOWN:
PDC_mouse_rect.left = PDC_mouse_rect.right =
LOWORD( lParam) / PDC_cxChar;
PDC_mouse_rect.top = PDC_mouse_rect.bottom =
HIWORD( lParam) / PDC_cyChar;
PDC_selecting_rectangle = (wParam & MK_SHIFT);
SetCapture( hwnd);
button_down = 0;
break;
case WM_LBUTTONUP:
button_up = 0;
ReleaseCapture( );
if( (PDC_mouse_rect.left != PDC_mouse_rect.right ||
PDC_mouse_rect.top != PDC_mouse_rect.bottom) &&
(PDC_mouse_rect.right >= 0 && PDC_mouse_rect.left >= 0
&& curscr && curscr->_y) )
{
HandleBlockCopy();
}
PDC_mouse_rect.top = PDC_mouse_rect.bottom = -1;
break;
case WM_RBUTTONDOWN:
button_down = 2;
SetCapture( hwnd);
break;
case WM_RBUTTONUP:
button_up = 2;
ReleaseCapture( );
break;
case WM_MBUTTONDOWN:
button_down = 1;
SetCapture( hwnd);
break;
case WM_MBUTTONUP:
button_up = 1;
ReleaseCapture( );
break;
#if( PDC_MAX_MOUSE_BUTTONS >= 5)
case WM_XBUTTONDOWN:
button_down = ((wParam & MK_XBUTTON1) ? 3 : 4);
SetCapture( hwnd);
break;
case WM_XBUTTONUP:
#ifdef WRONG_WAY
button_up = ((wParam & MK_XBUTTON1) ? 3 : 4);
#endif
button_up = (((mouse_buttons_pressed & 8) ||
pdc_mouse_status.xbutton[0] & BUTTON_PRESSED) ? 3 : 4);
ReleaseCapture( );
break;
#endif
case WM_MOVE:
return 0 ;
case WM_ERASEBKGND:
return( 0);
case WM_PAINT:
if( hwnd && curscr )
{
HandlePaint( hwnd );
}
break;
case WM_KEYUP:
case WM_SYSKEYUP:
if( wParam == VK_MENU && numpad_unicode_value)
{
modified_key_to_return = numpad_unicode_value;
numpad_unicode_value = 0;
pdc_key_modifiers = 0;
}
if( modified_key_to_return )
{
add_key_to_queue( modified_key_to_return );
modified_key_to_return = 0;
}
break;
case WM_CHAR:
if( wParam != 9 || !(GetKeyState( VK_SHIFT) & 0x8000))
if( !key_already_handled)
add_key_to_queue( (int)wParam );
key_already_handled = FALSE;
break;
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
if( wParam < 225 && wParam > 0 )
{
HandleSyskeyDown( wParam, lParam, &modified_key_to_return );
}
return 0 ;
case WM_SYSCHAR:
return 0 ;
case WM_TIMER:
if( wParam != TIMER_ID_FOR_BLINKING )
{
static const int remap_table[PDC_MAX_MOUSE_BUTTONS] =
{ BUTTON1_PRESSED, BUTTON2_PRESSED, BUTTON3_PRESSED,
BUTTON4_PRESSED, BUTTON5_PRESSED };
modified_key_to_return = 0;
if( SP && (SP->_trap_mbe & remap_table[wParam]))
set_mouse( (const int) wParam, BUTTON_PRESSED, mouse_lParam);
KillTimer( PDC_hWnd, (int)wParam);
mouse_buttons_pressed ^= (1 << wParam);
}
else if( SP && curscr && curscr->_y)
{
HandleTimer( wParam );
}
break;
case WM_CLOSE:
{
if( !PDC_shutdown_key[FUNCTION_KEY_SHUT_DOWN])
{
final_cleanup( );
PDC_bDone = TRUE;
exit( 0);
}
else
add_key_to_queue( PDC_shutdown_key[FUNCTION_KEY_SHUT_DOWN]);
}
return( 0);
case WM_COMMAND:
case WM_SYSCOMMAND:
if( wParam == WM_EXIT_GRACELESSLY)
{
final_cleanup( );
PDC_bDone = TRUE;
exit( 0);
}
else if( wParam == WM_ENLARGE_FONT || wParam == WM_SHRINK_FONT)
{
adjust_font_size( (wParam == WM_ENLARGE_FONT) ? 1 : -1);
return( 0);
}
else if( wParam == WM_CHOOSE_FONT)
{
if( PDC_choose_a_new_font( ))
adjust_font_size( 0);
return( 0);
}
else if( wParam == WM_PASTE)
{
PDC_add_clipboard_to_key_queue( );
}
else if( wParam == WM_TOGGLE_MENU)
{
HandleMenuToggle( &ignore_resize);
}
break;
case WM_DESTROY:
PDC_LOG(("WM_DESTROY\n"));
PostQuitMessage (0) ;
PDC_bDone = TRUE;
return 0 ;
}
if( hwnd)
show_mouse_rect( hwnd, before_rect, PDC_mouse_rect);
if( button_down >= 0)
{
modified_key_to_return = 0;
SetTimer( hwnd, button_down, SP->mouse_wait, NULL);
mouse_buttons_pressed |= (1 << button_down);
mouse_lParam = lParam;
}
if( button_up >= 0)
{
int message_to_send = -1;
modified_key_to_return = 0;
if( (mouse_buttons_pressed >> button_up) & 1)
{
const uint64_t curr_click_time =
milliseconds_since_1970( );
static const int double_remap_table[PDC_MAX_MOUSE_BUTTONS] =
{ BUTTON1_DOUBLE_CLICKED, BUTTON2_DOUBLE_CLICKED,
BUTTON3_DOUBLE_CLICKED, BUTTON4_DOUBLE_CLICKED,
BUTTON5_DOUBLE_CLICKED };
static const int triple_remap_table[PDC_MAX_MOUSE_BUTTONS] =
{ BUTTON1_TRIPLE_CLICKED, BUTTON2_TRIPLE_CLICKED,
BUTTON3_TRIPLE_CLICKED, BUTTON4_TRIPLE_CLICKED,
BUTTON5_TRIPLE_CLICKED };
static int n_previous_clicks;
if( curr_click_time <
last_click_time[button_up] + 2 * SP->mouse_wait)
n_previous_clicks++;
else
n_previous_clicks = 0;
if( n_previous_clicks >= 2 &&
(SP->_trap_mbe & triple_remap_table[button_up]))
message_to_send = BUTTON_TRIPLE_CLICKED;
else if( n_previous_clicks >= 1 &&
(SP->_trap_mbe & double_remap_table[button_up]))
message_to_send = BUTTON_DOUBLE_CLICKED;
else
{
static const int remap_table[PDC_MAX_MOUSE_BUTTONS] =
{ BUTTON1_CLICKED, BUTTON2_CLICKED, BUTTON3_CLICKED,
BUTTON4_CLICKED, BUTTON5_CLICKED };
if( SP->_trap_mbe & remap_table[button_up])
message_to_send = BUTTON_CLICKED;
}
KillTimer( hwnd, button_up);
mouse_buttons_pressed ^= (1 << button_up);
last_click_time[button_up] = curr_click_time;
}
if( message_to_send == -1)
{
static const int remap_table[PDC_MAX_MOUSE_BUTTONS] =
{ BUTTON1_RELEASED, BUTTON2_RELEASED, BUTTON3_RELEASED,
BUTTON4_RELEASED, BUTTON5_RELEASED };
if( SP->_trap_mbe & remap_table[button_up])
message_to_send = BUTTON_RELEASED;
}
if( message_to_send != -1)
set_mouse( button_up, message_to_send, lParam);
}
return DefWindowProc( hwnd, message, wParam, lParam) ;
}
int PDC_set_function_key( const unsigned function, const int new_key)
{
int old_key = -1;
if( function < PDC_MAX_FUNCTION_KEYS)
{
old_key = PDC_shutdown_key[function];
PDC_shutdown_key[function] = new_key;
}
if( function == FUNCTION_KEY_SHUT_DOWN)
if( (new_key && !old_key) || (old_key && !new_key))
{
HMENU hMenu = GetSystemMenu( PDC_hWnd, FALSE);
if( new_key)
AppendMenu( hMenu, MF_STRING, WM_EXIT_GRACELESSLY, _T( "Kill"));
else
RemoveMenu( hMenu, WM_EXIT_GRACELESSLY, MF_BYCOMMAND);
}
return( old_key);
}
#ifdef MONITOR_DEFAULTTONEAREST
static void clip_or_center_rect_to_monitor( LPRECT prc)
{
HMONITOR hMonitor;
MONITORINFO mi;
RECT rc;
const int w = prc->right - prc->left;
const int h = prc->bottom - prc->top;
hMonitor = MonitorFromRect(prc, MONITOR_DEFAULTTONEAREST);
mi.cbSize = sizeof(mi);
GetMonitorInfo(hMonitor, &mi);
rc = mi.rcMonitor;
prc->left = max(rc.left, min(rc.right-w, prc->left));
prc->top = max(rc.top, min(rc.bottom-h, prc->top));
prc->right = prc->left + w;
prc->bottom = prc->top + h;
}
static void clip_or_center_window_to_monitor( HWND hwnd)
{
RECT rc;
GetWindowRect(hwnd, &rc);
clip_or_center_rect_to_monitor(&rc);
SetWindowPos(hwnd, NULL, rc.left, rc.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
}
#endif
INLINE int set_up_window( void)
{
WNDCLASS wndclass ;
HMENU hMenu;
HANDLE hInstance = GetModuleHandleA( NULL);
int n_default_columns = 80;
int n_default_rows = 25;
int xsize, ysize, window_style;
int xloc = CW_USEDEFAULT;
int yloc = CW_USEDEFAULT;
TCHAR WindowTitle[MAX_PATH];
const TCHAR *AppName = _T( "Curses_App");
HICON icon;
static bool wndclass_has_been_registered = FALSE;
if( !hInstance)
debug_printf( "No instance: %d\n", GetLastError( ));
originally_focussed_window = GetForegroundWindow( );
debug_printf( "hInstance %x\nOriginal window %x\n", hInstance, originally_focussed_window);
icon = get_app_icon();
if( !icon )
icon = LoadIcon( NULL, IDI_APPLICATION);
if( !wndclass_has_been_registered)
{
ATOM rval;
wndclass.style = CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = icon;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = AppName ;
rval = RegisterClass( &wndclass) ;
if( !rval)
{
const DWORD last_error = GetLastError( );
debug_printf( "RegisterClass failed: GetLastError = %lx\n", last_error);
return( -1);
}
wndclass_has_been_registered = TRUE;
}
get_app_name( WindowTitle, TRUE);
#ifdef PDC_WIDE
debug_printf( "WindowTitle = '%ls'\n", WindowTitle);
#endif
get_default_sizes_from_registry( &n_default_columns, &n_default_rows, &xloc, &yloc,
&menu_shown);
if( PDC_n_rows > 2 && PDC_n_cols > 2)
{
n_default_columns = PDC_n_cols;
n_default_rows = PDC_n_rows;
}
if( ttytype[1])
PDC_set_resize_limits( (unsigned char)ttytype[0],
(unsigned char)ttytype[1],
(unsigned char)ttytype[2],
(unsigned char)ttytype[3]);
debug_printf( "Size %d x %d, loc %d x %d; menu %d\n",
n_default_columns, n_default_rows, xloc, yloc, menu_shown);
get_character_sizes( NULL, &PDC_cxChar, &PDC_cyChar);
if( min_lines != max_lines || min_cols != max_cols)
window_style = ((n_default_columns == -1) ?
WS_MAXIMIZE | WS_OVERLAPPEDWINDOW : WS_OVERLAPPEDWINDOW);
else
window_style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
if( n_default_columns == -1)
xsize = ysize = CW_USEDEFAULT;
else
{
keep_size_within_bounds( &n_default_rows, &n_default_columns);
xsize = PDC_cxChar * n_default_columns;
ysize = PDC_cyChar * n_default_rows;
adjust_window_size( &xsize, &ysize, window_style, menu_shown);
}
PDC_hWnd = CreateWindow( AppName, WindowTitle, window_style,
xloc, yloc,
xsize, ysize,
NULL, (menu_shown ? set_menu( ) : NULL),
hInstance, NULL) ;
if( !PDC_hWnd)
{
const DWORD last_error = GetLastError( );
debug_printf( "CreateWindow failed; GetLastError = %ld", last_error);
return( -2);
}
hMenu = GetSystemMenu( PDC_hWnd, FALSE);
AppendMenu( hMenu, MF_STRING | (menu_shown ? MF_CHECKED : MF_UNCHECKED), WM_TOGGLE_MENU, _T( "Menu"));
AppendMenu( hMenu, MF_STRING, WM_CHOOSE_FONT, _T( "Choose Font"));
debug_printf( "menu set\n");
ShowWindow (PDC_hWnd,
(n_default_columns == -1) ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL);
debug_printf( "window shown\n");
ValidateRect( PDC_hWnd, NULL);
UpdateWindow (PDC_hWnd) ;
debug_printf( "window updated\n");
SetTimer( PDC_hWnd, TIMER_ID_FOR_BLINKING, 500, NULL);
debug_printf( "timer set\n");
#ifdef MONITOR_DEFAULTTONEAREST
clip_or_center_window_to_monitor( PDC_hWnd);
#endif
return( 0);
}
#define MAX_LINES 50000
#define MAX_COLUMNS 50000
int PDC_scr_open( int argc, char **argv)
{
int i, r, g, b;
HMODULE hntdll = GetModuleHandle( _T("ntdll.dll"));
if( hntdll)
wine_version = (wine_version_func)GetProcAddress(hntdll, "wine_get_version");
PDC_LOG(("PDC_scr_open() - called\n"));
SP = calloc(1, sizeof(SCREEN));
color_pair_indices = (short *)calloc(PDC_COLOR_PAIRS * 2, sizeof( short));
pdc_rgbs = (COLORREF *)calloc(N_COLORS, sizeof( COLORREF));
if (!SP || !color_pair_indices || !pdc_rgbs)
return ERR;
debug_printf( "colors alloc\n");
COLORS = N_COLORS;
for( i = 0; i < 16; i++)
{
const int intensity = ((i & 8) ? 0xff : 0xc0);
pdc_rgbs[i] = RGB( ((i & COLOR_RED) ? intensity : 0),
((i & COLOR_GREEN) ? intensity : 0),
((i & COLOR_BLUE) ? intensity : 0));
}
for( r = 0; r < 6; r++)
for( g = 0; g < 6; g++)
for( b = 0; b < 6; b++)
pdc_rgbs[i++] = RGB( r ? r * 40 + 55 : 0,
g ? g * 40 + 55 : 0,
b ? b * 40 + 55 : 0);
for( i = 0; i < 24; i++)
pdc_rgbs[i + 232] = RGB( i * 10 + 8, i * 10 + 8, i * 10 + 8);
SP->mouse_wait = PDC_CLICK_PERIOD;
SP->visibility = 0;
SP->curscol = SP->cursrow = 0;
SP->audible = TRUE;
SP->mono = FALSE;
if( argc && argv)
{
PDC_argc = argc;
PDC_argv = (char **)calloc( argc + 1, sizeof( char *));
for( i = 0; i < argc; i++)
{
PDC_argv[i] = (char *)malloc( strlen( argv[i]) + 1);
strcpy( PDC_argv[i], argv[i]);
}
}
if( set_up_window( ))
{
fprintf( stderr, "set_up_window failed\n");
return ERR;
}
debug_printf( "Back from set_up_window\n");
while( !PDC_get_rows( ))
;
debug_printf( "Back from PDC_get_rows\n");
SP->lines = PDC_get_rows();
SP->cols = PDC_get_columns();
if (SP->lines < 2 || SP->lines > MAX_LINES
|| SP->cols < 2 || SP->cols > MAX_COLUMNS)
{
fprintf(stderr, "LINES value must be >= 2 and <= %d: got %d\n",
MAX_LINES, SP->lines);
fprintf(stderr, "COLS value must be >= 2 and <= %d: got %d\n",
MAX_COLUMNS, SP->cols);
return ERR;
}
debug_printf( "...we're done\n");
return OK;
}
int PDC_resize_screen( int nlines, int ncols)
{
if( !stdscr)
{
PDC_n_rows = nlines;
PDC_n_cols = ncols;
return OK;
}
SP->resized = FALSE;
debug_printf( "Incoming: %d %d\n", nlines, ncols);
if( nlines >= 2 && ncols >= 2 && PDC_cxChar && PDC_cyChar && PDC_hWnd &&
!IsZoomed( PDC_hWnd) )
{
RECT rect, client_rect;
int new_width;
int new_height;
GetWindowRect( PDC_hWnd, &rect);
GetClientRect( PDC_hWnd, &client_rect);
debug_printf( "Outgoing: %d %d\n", nlines, ncols);
new_width = ncols * PDC_cxChar;
new_height = nlines * PDC_cyChar;
if( new_width != client_rect.right || new_height != client_rect.bottom)
{
add_resize_key = 0;
SetWindowPos( PDC_hWnd, 0, 0, 0,
new_width + (rect.right - rect.left) - client_rect.right,
new_height + (rect.bottom - rect.top) - client_rect.bottom,
SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW);
}
}
return OK;
}
void PDC_reset_prog_mode(void)
{
PDC_LOG(("PDC_reset_prog_mode() - called.\n"));
#ifdef NOT_CURRENTLY_IN_USE
if( PDC_bDone == FALSE && PDC_hWnd)
{
PDC_bDone = TRUE;
SetForegroundWindow( PDC_hWnd);
}
#endif
}
void PDC_reset_shell_mode(void)
{
}
void PDC_restore_screen_mode(int i)
{
}
void PDC_save_screen_mode(int i)
{
}
static short get_pair( const chtype ch)
{
return( (short)( (ch & A_COLOR) >> PDC_COLOR_SHIFT));
}
void PDC_init_pair( short pair, short fg, short bg)
{
if( color_pair_indices[pair] != fg ||
color_pair_indices[pair + PDC_COLOR_PAIRS] != bg)
{
color_pair_indices[pair] = fg;
color_pair_indices[pair + PDC_COLOR_PAIRS] = bg;
if( curscr && curscr->_y)
{
int i;
for( i = 0; i < SP->lines; i++)
if( curscr->_y[i])
{
int j = 0, n_chars;
chtype *line = curscr->_y[i];
while( j < SP->cols && get_pair( *line) != pair)
{
j++;
line++;
}
n_chars = SP->cols - j;
while( n_chars && get_pair( line[n_chars - 1]) != pair)
n_chars--;
if( n_chars)
PDC_transform_line( i, j, n_chars, line);
}
}
}
}
int PDC_pair_content( short pair, short *fg, short *bg)
{
*fg = color_pair_indices[pair];
*bg = color_pair_indices[pair + PDC_COLOR_PAIRS];
return OK;
}
bool PDC_can_change_color(void)
{
return TRUE;
}
int PDC_color_content( short color, short *red, short *green, short *blue)
{
COLORREF col = pdc_rgbs[color];
*red = DIVROUND(GetRValue(col) * 1000, 255);
*green = DIVROUND(GetGValue(col) * 1000, 255);
*blue = DIVROUND(GetBValue(col) * 1000, 255);
return OK;
}
static int color_used_for_this_char( const chtype c, const int idx)
{
const int color = get_pair( c);
const int rval = (color_pair_indices[color] == idx ||
color_pair_indices[color + PDC_COLOR_PAIRS] == idx);
return( rval);
}
int PDC_init_color( short color, short red, short green, short blue)
{
const COLORREF new_rgb = RGB(DIVROUND(red * 255, 1000),
DIVROUND(green * 255, 1000),
DIVROUND(blue * 255, 1000));
if( pdc_rgbs[color] != new_rgb)
{
pdc_rgbs[color] = new_rgb;
if( curscr && curscr->_y)
{
int i;
for( i = 0; i < SP->lines; i++)
if( curscr->_y[i])
{
int j = 0, n_chars;
chtype *line = curscr->_y[i];
while( j < SP->cols
&& !color_used_for_this_char( *line, color))
{
j++;
line++;
}
n_chars = SP->cols - j;
while( n_chars &&
!color_used_for_this_char( line[n_chars - 1], color))
n_chars--;
if( n_chars)
PDC_transform_line( i, j, n_chars, line);
}
}
}
return OK;
}