2384 lines
43 KiB
C++
2384 lines
43 KiB
C++
/* Eigenmath by George Weigt
|
|
|
|
This file does all the things required by the Windows API.
|
|
|
|
The starting point for a symbolic computation is in run.c
|
|
|
|
Input is scanned in scan.c
|
|
|
|
Expression evaluation is done in eval.c
|
|
|
|
Output is formatted in cmdisplay.c
|
|
|
|
The window display code is in window.c
|
|
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include <commdlg.h>
|
|
#include <stdio.h>
|
|
#define _USE_MATH_DEFINES // for MS C++
|
|
#include <math.h>
|
|
#include <time.h>
|
|
|
|
#include "help.h"
|
|
|
|
extern void run(char *);
|
|
extern void clear(void);
|
|
extern void draw_display(void);
|
|
extern void printstr(char *);
|
|
extern void update_cmd_history(char *);
|
|
extern void echo_input(char *);
|
|
extern void print_mem_info(void);
|
|
extern char *get_cmd_history(void);
|
|
|
|
void update_display(void);
|
|
|
|
int line_height = 20;
|
|
int left_margin = 5;
|
|
int right_margin = 5;
|
|
int main_client_width;
|
|
int main_client_height;
|
|
static int scroll_bar_width;
|
|
int display_x;
|
|
int display_y;
|
|
int display_width;
|
|
int display_height;
|
|
int max_x;
|
|
int max_y;
|
|
int total_w;
|
|
int total_h;
|
|
int update_display_request;
|
|
extern int esc_flag;
|
|
|
|
static int running;
|
|
static unsigned int timer;
|
|
static int edit_mode;
|
|
|
|
HINSTANCE hinst;
|
|
HINSTANCE hInst;
|
|
HWND main_window;
|
|
HWND input_window;
|
|
HWND edit_window;
|
|
HWND hscroll;
|
|
HWND vscroll;
|
|
#define NBUTTON 8
|
|
HWND button[NBUTTON];
|
|
HDC draw_hdc;
|
|
HDC run_hdc;
|
|
HMENU main_menu;
|
|
|
|
#define NFONT 11
|
|
|
|
HFONT display_font[NFONT];
|
|
|
|
struct text_metric {
|
|
int ascent, descent, width;
|
|
} text_metric[NFONT];
|
|
|
|
#define SMALL_FONT 1
|
|
#define DEFAULT_FONT 2
|
|
#define TIMES_FONT 3
|
|
#define ITALIC_TIMES_FONT 4
|
|
#define SYMBOL_FONT 5
|
|
#define ITALIC_SYMBOL_FONT 6
|
|
#define SMALL_TIMES_FONT 7
|
|
#define SMALL_ITALIC_TIMES_FONT 8
|
|
#define SMALL_SYMBOL_FONT 9
|
|
#define SMALL_ITALIC_SYMBOL_FONT 10
|
|
|
|
#define DRAW_HRULE 20
|
|
#define DRAW_LEFT_BRACKET 21
|
|
#define DRAW_RIGHT_BRACKET 22
|
|
#define DRAW_LINE 23
|
|
|
|
static void MyRegisterClass(HINSTANCE hInstance);
|
|
BOOL InitInstance(HINSTANCE, int);
|
|
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
|
|
|
|
void do_up_arrow(void);
|
|
void do_down_arrow(void);
|
|
void do_fonts(void);
|
|
void fill_font_metric_array(void);
|
|
void do_more_setup(void);
|
|
|
|
static void goto_edit_mode(void);
|
|
static void goto_calc_mode(void);
|
|
static void move_input_window(void);
|
|
static void move_edit_window(void);
|
|
static void move_buttons(void);
|
|
static void move_scroll_bars(void);
|
|
static void create_menu(void);
|
|
static void do_vscroll(int, int);
|
|
static void do_hscroll(int, int);
|
|
static void update_scroll_bars(void);
|
|
static void move_bits_up(int);
|
|
static void move_bits_down(int);
|
|
static void run_script(void);
|
|
static void do_new(void);
|
|
static void do_save(void);
|
|
static void do_saveas(void);
|
|
static void do_open(void);
|
|
static void save_file(void);
|
|
static void do_page_setup(void);
|
|
static void do_print(void);
|
|
static void do_button(char *);
|
|
static void do_enter(void);
|
|
static void send_user_event(void);
|
|
static void activate_controls(void);
|
|
static void deactivate_controls(void);
|
|
static void process_user_event(void);
|
|
static void copy_all(void);
|
|
static void do_create_script(void);
|
|
void update_curr_cmd(char *);
|
|
|
|
enum {
|
|
ID_BASE = 40000,
|
|
|
|
// events
|
|
|
|
ID_USER_EVENT,
|
|
ID_ESC,
|
|
ID_ENTER,
|
|
ID_UP_ARROW,
|
|
ID_DOWN_ARROW,
|
|
|
|
// application buttons
|
|
|
|
ID_CLEAR,
|
|
ID_DERIVATIVE,
|
|
ID_DRAW,
|
|
ID_FLOAT,
|
|
ID_INTEGRAL,
|
|
ID_SIMPLIFY,
|
|
ID_EDIT_SCRIPT,
|
|
ID_RUN_SCRIPT,
|
|
|
|
// file menu
|
|
|
|
ID_NEW,
|
|
ID_OPEN,
|
|
ID_SAVE,
|
|
ID_SAVEAS,
|
|
ID_PAGE_SETUP,
|
|
ID_PRINT,
|
|
|
|
// edit menu
|
|
|
|
ID_UNDO,
|
|
ID_CUT,
|
|
ID_COPY,
|
|
ID_PASTE,
|
|
|
|
// asterisk menu
|
|
|
|
ID_COPY_DISPLAY,
|
|
ID_CREATE_SCRIPT,
|
|
|
|
// help menu
|
|
|
|
ID_HELP_ABS,
|
|
ID_HELP_ADJ,
|
|
ID_HELP_ARCCOS,
|
|
ID_HELP_ARCCOSH,
|
|
ID_HELP_ARCSIN,
|
|
ID_HELP_ARCSINH,
|
|
ID_HELP_ARCTAN,
|
|
ID_HELP_ARCTANH,
|
|
ID_HELP_ARG,
|
|
ID_HELP_BESSELJ,
|
|
ID_HELP_CHOOSE,
|
|
ID_HELP_CIRCEXP,
|
|
ID_HELP_COEFF,
|
|
ID_HELP_COFACTOR,
|
|
ID_HELP_CONJ,
|
|
ID_HELP_CONTRACT,
|
|
ID_HELP_COS,
|
|
ID_HELP_COSH,
|
|
ID_HELP_DEG,
|
|
ID_HELP_DENOMINATOR,
|
|
ID_HELP_DERIVATIVE,
|
|
ID_HELP_DET,
|
|
ID_HELP_DOT,
|
|
ID_HELP_ERF,
|
|
ID_HELP_ERFC,
|
|
ID_HELP_EVAL,
|
|
ID_HELP_EXP,
|
|
ID_HELP_EXPCOS,
|
|
ID_HELP_EXPSIN,
|
|
ID_HELP_FACTOR,
|
|
ID_HELP_FACTORIAL,
|
|
ID_HELP_FOR,
|
|
ID_HELP_GRADIENT,
|
|
ID_HELP_HERMITE,
|
|
ID_HELP_IMAG,
|
|
ID_HELP_INTEGRAL,
|
|
ID_HELP_INV,
|
|
ID_HELP_LAGUERRE,
|
|
ID_HELP_LEGENDRE,
|
|
ID_HELP_LOG,
|
|
ID_HELP_MAG,
|
|
ID_HELP_NUMERATOR,
|
|
ID_HELP_OUTER,
|
|
ID_HELP_POLAR,
|
|
ID_HELP_PRODUCT,
|
|
ID_HELP_QUOTIENT,
|
|
ID_HELP_REAL,
|
|
ID_HELP_RECT,
|
|
ID_HELP_SIN,
|
|
ID_HELP_SINH,
|
|
ID_HELP_SQRT,
|
|
ID_HELP_SUM,
|
|
ID_HELP_TAN,
|
|
ID_HELP_TANH,
|
|
ID_HELP_TAYLOR,
|
|
ID_HELP_TRANSPOSE,
|
|
ID_HELP_UNIT,
|
|
ID_HELP_ZERO,
|
|
};
|
|
|
|
#define NACCEL 7
|
|
|
|
ACCEL accel[NACCEL] = {
|
|
{FCONTROL, 15, ID_OPEN}, // ^O
|
|
{FCONTROL, 19, ID_SAVE}, // ^S
|
|
{FCONTROL, 26, ID_UNDO}, // ^Z
|
|
{FCONTROL, 24, ID_CUT}, // ^X
|
|
{FCONTROL, 3, ID_COPY}, // ^C
|
|
{FCONTROL, 22, ID_PASTE}, // ^V
|
|
{FCONTROL, 27, ID_ESC}, // ^[
|
|
};
|
|
|
|
int APIENTRY _tWinMain(HINSTANCE hInstance,
|
|
HINSTANCE hPrevInstance,
|
|
LPTSTR lpCmdLine,
|
|
int nCmdShow)
|
|
{
|
|
int tmp;
|
|
MSG msg;
|
|
HACCEL haccel;
|
|
|
|
hinst = hInstance;
|
|
|
|
MyRegisterClass(hInstance);
|
|
|
|
// Perform application initialization:
|
|
if (!InitInstance (hInstance, nCmdShow))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
do_fonts();
|
|
|
|
fill_font_metric_array();
|
|
|
|
create_menu();
|
|
|
|
do_more_setup();
|
|
|
|
haccel = CreateAcceleratorTable(accel, NACCEL);
|
|
|
|
SetTimer(main_window, 0, 1000, NULL);
|
|
|
|
while (1) {
|
|
|
|
tmp = GetMessage(&msg, NULL, 0, 0);
|
|
|
|
if (tmp < 1)
|
|
break;
|
|
|
|
tmp = TranslateAccelerator(main_window, haccel, &msg);
|
|
|
|
if (tmp == 0) {
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
|
|
if (msg.hwnd == input_window && msg.message == WM_KEYDOWN) {
|
|
switch (msg.wParam) {
|
|
case 13:
|
|
PostMessage(main_window, ID_ENTER, 0, 0);
|
|
break;
|
|
case VK_UP:
|
|
PostMessage(main_window, ID_UP_ARROW, 0, 0);
|
|
break;
|
|
case VK_DOWN:
|
|
PostMessage(main_window, ID_DOWN_ARROW, 0, 0);
|
|
break;
|
|
case VK_PRIOR:
|
|
PostMessage(
|
|
main_window,
|
|
WM_VSCROLL,
|
|
SB_PAGEUP,
|
|
(LPARAM) vscroll);
|
|
break;
|
|
case VK_NEXT:
|
|
PostMessage(
|
|
main_window,
|
|
WM_VSCROLL,
|
|
SB_PAGEDOWN,
|
|
(LPARAM) vscroll);
|
|
break;
|
|
case VK_HOME:
|
|
PostMessage(
|
|
main_window,
|
|
WM_VSCROLL,
|
|
SB_TOP,
|
|
(LPARAM) vscroll);
|
|
break;
|
|
case VK_END:
|
|
PostMessage(
|
|
main_window,
|
|
WM_VSCROLL,
|
|
SB_BOTTOM,
|
|
(LPARAM) vscroll);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return (int) msg.wParam;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// FUNCTION: MyRegisterClass()
|
|
//
|
|
// PURPOSE: Registers the window class.
|
|
//
|
|
// COMMENTS:
|
|
//
|
|
// This function and its usage are only necessary if you want this code
|
|
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
|
|
// function that was added to Windows 95. It is important to call this function
|
|
// so that the application will get 'well formed' small icons associated
|
|
// with it.
|
|
//
|
|
|
|
static void
|
|
MyRegisterClass(HINSTANCE hInstance)
|
|
{
|
|
static WNDCLASSEX wcex;
|
|
|
|
wcex.cbSize = sizeof(WNDCLASSEX);
|
|
wcex.style = CS_HREDRAW | CS_VREDRAW;
|
|
wcex.lpfnWndProc = (WNDPROC)WndProc;
|
|
wcex.cbClsExtra = 0;
|
|
wcex.cbWndExtra = 0;
|
|
wcex.hInstance = hInstance;
|
|
wcex.hIcon = LoadIcon(hInstance, (LPCSTR) IDI_ICON1);
|
|
//wcex.hIcon = CreateIcon(hInstance, 0, 0, 0, 0, NULL, NULL);
|
|
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
|
wcex.lpszMenuName = NULL;
|
|
wcex.lpszClassName = "Eigenmath";
|
|
wcex.hIconSm = NULL;
|
|
|
|
RegisterClassEx(&wcex);
|
|
}
|
|
|
|
//
|
|
// FUNCTION: InitInstance(HANDLE, int)
|
|
//
|
|
// PURPOSE: Saves instance handle and creates main window
|
|
//
|
|
// COMMENTS:
|
|
//
|
|
// In this function, we save the instance handle in a global variable and
|
|
// create and display the main program window.
|
|
//
|
|
|
|
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
|
|
{
|
|
hInst = hInstance; // Store instance handle in our global variable
|
|
|
|
main_window = CreateWindow(
|
|
"Eigenmath",
|
|
"Eigenmath 129",
|
|
WS_OVERLAPPEDWINDOW,
|
|
CW_USEDEFAULT, 0,
|
|
// CW_USEDEFAULT, 0,
|
|
800, 540,
|
|
NULL,
|
|
NULL,
|
|
hInstance,
|
|
NULL);
|
|
|
|
ShowWindow(main_window, nCmdShow);
|
|
UpdateWindow(main_window);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static struct {
|
|
char *s;
|
|
long long id;
|
|
} main_button[NBUTTON] = {
|
|
{"Clear", ID_CLEAR},
|
|
{"Draw", ID_DRAW},
|
|
{"Simplify", ID_SIMPLIFY},
|
|
{"Float", ID_FLOAT},
|
|
{"Derivative", ID_DERIVATIVE},
|
|
{"Integral", ID_INTEGRAL},
|
|
{"Edit Script", ID_EDIT_SCRIPT},
|
|
{"Run Script", ID_RUN_SCRIPT},
|
|
};
|
|
|
|
void
|
|
do_more_setup(void)
|
|
{
|
|
int h, i, j, k, w, x, y;
|
|
RECT r;
|
|
|
|
GetClientRect(main_window, &r);
|
|
|
|
main_client_width = r.right;
|
|
main_client_height = r.bottom;
|
|
|
|
vscroll = CreateWindow(
|
|
"SCROLLBAR",
|
|
NULL,
|
|
WS_CHILD | WS_VISIBLE | SBS_VERT | SBS_RIGHTALIGN,
|
|
0, 0,
|
|
main_client_width, main_client_height - 3 * line_height,
|
|
main_window,
|
|
NULL,
|
|
hinst,
|
|
NULL);
|
|
|
|
GetWindowRect(vscroll, &r);
|
|
|
|
scroll_bar_width = r.right - r.left;
|
|
|
|
display_width = main_client_width - scroll_bar_width;
|
|
display_height = main_client_height - 3 * line_height - scroll_bar_width;
|
|
|
|
// move the scroll bar to adjust for its width
|
|
|
|
x = display_width;
|
|
y = 0;
|
|
w = scroll_bar_width;
|
|
h = display_height;
|
|
|
|
MoveWindow(vscroll, x, y, w, h, TRUE);
|
|
|
|
x = 0;
|
|
y = display_height;
|
|
w = display_width;
|
|
h = scroll_bar_width;
|
|
|
|
hscroll = CreateWindow(
|
|
"SCROLLBAR",
|
|
NULL,
|
|
WS_CHILD | WS_VISIBLE | SBS_HORZ,
|
|
x, y,
|
|
w, h,
|
|
main_window,
|
|
NULL,
|
|
hinst,
|
|
NULL);
|
|
|
|
x = 0;
|
|
y = main_client_height - 3 * line_height;
|
|
w = main_client_width;
|
|
h = line_height;
|
|
|
|
input_window = CreateWindow(
|
|
"EDIT",
|
|
NULL,
|
|
WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL,
|
|
x, y,
|
|
w, h,
|
|
main_window,
|
|
NULL,
|
|
hinst,
|
|
NULL);
|
|
|
|
SendMessage(input_window, WM_SETFONT, (WPARAM) display_font[DEFAULT_FONT], 0);
|
|
|
|
SetFocus(input_window);
|
|
|
|
edit_window = CreateWindow(
|
|
"EDIT",
|
|
NULL,
|
|
WS_CHILD | WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN,
|
|
0, 0,
|
|
main_client_width, main_client_height - 2 * line_height,
|
|
main_window,
|
|
NULL,
|
|
hinst,
|
|
NULL);
|
|
|
|
SendMessage(edit_window, WM_SETFONT, (WPARAM) display_font[DEFAULT_FONT], 0);
|
|
|
|
// create buttons
|
|
|
|
for (i = 0; i < NBUTTON; i++) {
|
|
j = i * main_client_width / NBUTTON;
|
|
k = (i + 1) * main_client_width / NBUTTON;
|
|
button[i] = CreateWindow(
|
|
"BUTTON",
|
|
main_button[i].s,
|
|
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
|
|
j, main_client_height - 2 * line_height,
|
|
k - j, 2 * line_height,
|
|
main_window,
|
|
(HMENU) main_button[i].id,
|
|
hinst,
|
|
NULL);
|
|
SendMessage(
|
|
button[i],
|
|
WM_SETFONT,
|
|
(WPARAM) GetStockObject(ANSI_VAR_FONT),
|
|
0);
|
|
#if 0
|
|
button[2 * i + 1] = CreateWindow(
|
|
"BUTTON",
|
|
main_button[2 * i + 1].s,
|
|
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
|
|
j, main_client_height - line_height,
|
|
k - j, line_height,
|
|
main_window,
|
|
(HMENU) main_button[2 * i + 1].id,
|
|
hinst,
|
|
NULL);
|
|
SendMessage(
|
|
button[2 * i + 1],
|
|
WM_SETFONT,
|
|
(WPARAM) GetStockObject(ANSI_VAR_FONT),
|
|
0);
|
|
#endif
|
|
}
|
|
|
|
update_scroll_bars();
|
|
}
|
|
|
|
static struct {
|
|
char *s;
|
|
int id;
|
|
} menu[] = {
|
|
|
|
{"File", 0},
|
|
{"New", ID_NEW},
|
|
{"Open\tCtrl+O", ID_OPEN},
|
|
{"Save\tCtrl+S", ID_SAVE},
|
|
{"Save As", ID_SAVEAS},
|
|
//{"-", 0},
|
|
//{"Page Setup", ID_PAGE_SETUP},
|
|
//{"Print", ID_PRINT},
|
|
{0, 0},
|
|
|
|
{"Edit", 0},
|
|
{"Undo\tCtrl+Z", ID_UNDO},
|
|
{"Cut\tCtrl+X", ID_CUT},
|
|
{"Copy\tCtrl+C", ID_COPY},
|
|
{"Paste\tCtrl+V", ID_PASTE},
|
|
{0, 0},
|
|
|
|
{"*", 0},
|
|
{"Copy display to clipboard", ID_COPY_DISPLAY},
|
|
{"Create script from command history", ID_CREATE_SCRIPT},
|
|
{0, 0},
|
|
|
|
{"Help", 0},
|
|
|
|
{"Complex number functions", 0},
|
|
{"arg", ID_HELP_ARG},
|
|
{"conj", ID_HELP_CONJ},
|
|
{"imag", ID_HELP_IMAG},
|
|
{"mag", ID_HELP_MAG},
|
|
{"polar", ID_HELP_POLAR},
|
|
{"real", ID_HELP_REAL},
|
|
{"rect", ID_HELP_RECT},
|
|
{0, 0},
|
|
|
|
{"Polynomial functions", 0},
|
|
{"coeff", ID_HELP_COEFF},
|
|
{"deg", ID_HELP_DEG},
|
|
{"quotient", ID_HELP_QUOTIENT},
|
|
{0, 0},
|
|
|
|
{"Linear algebra functions", 0},
|
|
{"adj", ID_HELP_ADJ},
|
|
{"cofactor", ID_HELP_COFACTOR},
|
|
{"contract", ID_HELP_CONTRACT},
|
|
{"det", ID_HELP_DET},
|
|
{"dot", ID_HELP_DOT},
|
|
{"inv", ID_HELP_INV},
|
|
{"outer", ID_HELP_OUTER},
|
|
{"transpose", ID_HELP_TRANSPOSE},
|
|
{"unit", ID_HELP_UNIT},
|
|
{"zero", ID_HELP_ZERO},
|
|
{0, 0},
|
|
|
|
{"Calculus functions", 0},
|
|
{"derivative", ID_HELP_DERIVATIVE},
|
|
{"gradient", ID_HELP_GRADIENT},
|
|
{"integral", ID_HELP_INTEGRAL},
|
|
{"taylor", ID_HELP_TAYLOR},
|
|
{0, 0},
|
|
|
|
{"Exponential functions", 0},
|
|
{"circexp", ID_HELP_CIRCEXP},
|
|
{"exp", ID_HELP_EXP},
|
|
{"expcos", ID_HELP_EXPCOS},
|
|
{"expsin", ID_HELP_EXPSIN},
|
|
{"log", ID_HELP_LOG},
|
|
{0, 0},
|
|
|
|
{"Circular functions", 0},
|
|
{"arccos", ID_HELP_ARCCOS},
|
|
{"arcsin", ID_HELP_ARCSIN},
|
|
{"arctan", ID_HELP_ARCTAN},
|
|
{"cos", ID_HELP_COS},
|
|
{"sin", ID_HELP_SIN},
|
|
{"tan", ID_HELP_TAN},
|
|
{0, 0},
|
|
|
|
{"Hyperbolic functions", 0},
|
|
{"arccosh", ID_HELP_ARCCOSH},
|
|
{"arcsinh", ID_HELP_ARCSINH},
|
|
{"arctanh", ID_HELP_ARCTANH},
|
|
{"cosh", ID_HELP_COSH},
|
|
{"sinh", ID_HELP_SINH},
|
|
{"tanh", ID_HELP_TANH},
|
|
{0, 0},
|
|
|
|
{"Special functions", 0},
|
|
{"besselj", ID_HELP_BESSELJ},
|
|
{"hermite", ID_HELP_HERMITE},
|
|
{"laguerre", ID_HELP_LAGUERRE},
|
|
{"legendre", ID_HELP_LEGENDRE},
|
|
{0, 0},
|
|
|
|
{"Other functions", 0},
|
|
{"abs", ID_HELP_ABS},
|
|
{"choose", ID_HELP_CHOOSE},
|
|
{"denominator", ID_HELP_DENOMINATOR},
|
|
{"erf", ID_HELP_ERF},
|
|
{"erfc", ID_HELP_ERFC},
|
|
{"eval", ID_HELP_EVAL},
|
|
{"factor", ID_HELP_FACTOR},
|
|
{"factorial", ID_HELP_FACTORIAL},
|
|
{"for", ID_HELP_FOR},
|
|
{"numerator", ID_HELP_NUMERATOR},
|
|
{"product", ID_HELP_PRODUCT},
|
|
{"sqrt", ID_HELP_SQRT},
|
|
{"sum", ID_HELP_SUM},
|
|
{0, 0},
|
|
|
|
{0, 0}, // end of 'examples' menu
|
|
|
|
{0, 0}, // end
|
|
};
|
|
|
|
static void
|
|
create_menu(void)
|
|
{
|
|
int k = 0, level = 0;
|
|
char *s[2];
|
|
HMENU hmenu[3];
|
|
|
|
hmenu[0] = CreateMenu();
|
|
|
|
while (1) {
|
|
if (menu[k].s == NULL) {
|
|
if (level) {
|
|
AppendMenu(
|
|
hmenu[level - 1],
|
|
MF_POPUP | MF_ENABLED | MF_STRING,
|
|
(UINT_PTR) hmenu[level],
|
|
s[level - 1]);
|
|
level--;
|
|
k++;
|
|
continue;
|
|
} else
|
|
break;
|
|
}
|
|
|
|
if (menu[k].s[0] == '-') {
|
|
AppendMenu(
|
|
hmenu[level],
|
|
MF_SEPARATOR,
|
|
0,
|
|
0);
|
|
k++;
|
|
continue;
|
|
}
|
|
|
|
if (menu[k].id == 0) {
|
|
s[level] = menu[k].s;
|
|
level++;
|
|
hmenu[level] = CreatePopupMenu();
|
|
k++;
|
|
continue;
|
|
}
|
|
|
|
AppendMenu(
|
|
hmenu[level],
|
|
MF_ENABLED | MF_STRING,
|
|
menu[k].id,
|
|
menu[k].s);
|
|
|
|
k++;
|
|
}
|
|
|
|
SetMenu(main_window, hmenu[0]);
|
|
|
|
main_menu = hmenu[0];
|
|
}
|
|
|
|
// FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
|
|
//
|
|
// PURPOSE: Processes messages for the main window.
|
|
//
|
|
// WM_COMMAND - process the application menu
|
|
// WM_PAINT - Paint the main window
|
|
// WM_DESTROY - post a quit message and return
|
|
//
|
|
//
|
|
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
int hi, lo;
|
|
PAINTSTRUCT ps;
|
|
RECT r;
|
|
|
|
switch (message) {
|
|
case ID_USER_EVENT:
|
|
process_user_event();
|
|
break;
|
|
case ID_ENTER:
|
|
if (running)
|
|
break;
|
|
do_enter();
|
|
break;
|
|
case ID_UP_ARROW:
|
|
if (running)
|
|
break;
|
|
do_up_arrow();
|
|
break;
|
|
case ID_DOWN_ARROW:
|
|
if (running)
|
|
break;
|
|
do_down_arrow();
|
|
break;
|
|
case WM_TIMER:
|
|
if (running == 1)
|
|
send_user_event();
|
|
break;
|
|
case WM_ACTIVATE:
|
|
if (edit_mode == 0)
|
|
SetFocus(input_window);
|
|
else
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
break;
|
|
case WM_SIZE:
|
|
GetClientRect(main_window, &r);
|
|
main_client_width = r.right;
|
|
main_client_height = r.bottom;
|
|
display_width = main_client_width - scroll_bar_width;
|
|
display_height = main_client_height - 3 * line_height - scroll_bar_width;
|
|
move_input_window();
|
|
move_edit_window();
|
|
move_buttons();
|
|
move_scroll_bars();
|
|
max_y = total_h - display_height;
|
|
if (max_y < 0)
|
|
max_y = 0;
|
|
if (display_y > max_y)
|
|
display_y = max_y;
|
|
update_scroll_bars();
|
|
PostMessage(main_window, WM_PAINT, 0, 0);
|
|
break;
|
|
case WM_COMMAND:
|
|
hi = HIWORD(wParam);
|
|
lo = LOWORD(wParam);
|
|
switch (lo) {
|
|
case ID_ESC:
|
|
esc_flag = 1;
|
|
break;
|
|
case ID_NEW:
|
|
if (running)
|
|
break;
|
|
do_new();
|
|
break;
|
|
case ID_OPEN:
|
|
if (running)
|
|
break;
|
|
do_open();
|
|
break;
|
|
case ID_SAVE:
|
|
do_save();
|
|
break;
|
|
case ID_SAVEAS:
|
|
do_saveas();
|
|
break;
|
|
// case ID_PAGE_SETUP:
|
|
// do_page_setup();
|
|
// break;
|
|
// case ID_PRINT:
|
|
// do_print();
|
|
// break;
|
|
|
|
case ID_UNDO:
|
|
if (running)
|
|
break;
|
|
if (edit_mode == 0)
|
|
SendMessage(input_window, WM_UNDO, 0, 0);
|
|
else
|
|
SendMessage(edit_window, WM_UNDO, 0, 0);
|
|
break;
|
|
case ID_CUT:
|
|
if (running)
|
|
break;
|
|
if (edit_mode == 0)
|
|
SendMessage(input_window, WM_CUT, 0, 0);
|
|
else
|
|
SendMessage(edit_window, WM_CUT, 0, 0);
|
|
break;
|
|
case ID_COPY:
|
|
if (running)
|
|
break;
|
|
if (edit_mode == 0)
|
|
SendMessage(input_window, WM_COPY, 0, 0);
|
|
else
|
|
SendMessage(edit_window, WM_COPY, 0, 0);
|
|
break;
|
|
case ID_PASTE:
|
|
if (running)
|
|
break;
|
|
if (edit_mode == 0)
|
|
SendMessage(input_window, WM_PASTE, 0, 0);
|
|
else
|
|
SendMessage(edit_window, WM_PASTE, 0, 0);
|
|
break;
|
|
|
|
// "asterisk" pull-down menu
|
|
|
|
case ID_COPY_DISPLAY:
|
|
copy_all();
|
|
break;
|
|
case ID_CREATE_SCRIPT:
|
|
if (running)
|
|
break;
|
|
do_create_script();
|
|
break;
|
|
|
|
// linear algebra
|
|
|
|
case ID_HELP_ADJ:
|
|
HELP(help_adj);
|
|
break;
|
|
case ID_HELP_COFACTOR:
|
|
HELP(help_cofactor);
|
|
break;
|
|
case ID_HELP_CONTRACT:
|
|
HELP(help_contract);
|
|
break;
|
|
case ID_HELP_DET:
|
|
HELP(help_det);
|
|
break;
|
|
case ID_HELP_DOT:
|
|
HELP(help_dot);
|
|
break;
|
|
case ID_HELP_INV:
|
|
HELP(help_inv);
|
|
break;
|
|
case ID_HELP_OUTER:
|
|
HELP(help_outer);
|
|
break;
|
|
case ID_HELP_TRANSPOSE:
|
|
HELP(help_transpose);
|
|
break;
|
|
case ID_HELP_UNIT:
|
|
HELP(help_unit);
|
|
break;
|
|
case ID_HELP_ZERO:
|
|
HELP(help_zero);
|
|
break;
|
|
|
|
// calculus
|
|
|
|
case ID_HELP_DERIVATIVE:
|
|
HELP(help_derivative);
|
|
break;
|
|
case ID_HELP_GRADIENT:
|
|
HELP(help_gradient);
|
|
break;
|
|
case ID_HELP_INTEGRAL:
|
|
HELP(help_integral);
|
|
break;
|
|
|
|
// complex number functions
|
|
|
|
case ID_HELP_ARG:
|
|
HELP(help_arg);
|
|
break;
|
|
case ID_HELP_CONJ:
|
|
HELP(help_conj);
|
|
break;
|
|
case ID_HELP_IMAG:
|
|
HELP(help_imag);
|
|
break;
|
|
case ID_HELP_MAG:
|
|
HELP(help_mag);
|
|
break;
|
|
case ID_HELP_POLAR:
|
|
HELP(help_polar);
|
|
break;
|
|
case ID_HELP_REAL:
|
|
HELP(help_real);
|
|
break;
|
|
case ID_HELP_RECT:
|
|
HELP(help_rect);
|
|
break;
|
|
|
|
// circular functions
|
|
|
|
case ID_HELP_ARCCOS:
|
|
HELP(help_arccos);
|
|
break;
|
|
case ID_HELP_ARCSIN:
|
|
HELP(help_arcsin);
|
|
break;
|
|
case ID_HELP_ARCTAN:
|
|
HELP(help_arctan);
|
|
break;
|
|
case ID_HELP_COS:
|
|
HELP(help_cos);
|
|
break;
|
|
case ID_HELP_SIN:
|
|
HELP(help_sin);
|
|
break;
|
|
case ID_HELP_TAN:
|
|
HELP(help_tan);
|
|
break;
|
|
|
|
// hyperbolic functions
|
|
|
|
case ID_HELP_ARCCOSH:
|
|
HELP(help_arccosh);
|
|
break;
|
|
case ID_HELP_ARCSINH:
|
|
HELP(help_arcsinh);
|
|
break;
|
|
case ID_HELP_ARCTANH:
|
|
HELP(help_arctanh);
|
|
break;
|
|
case ID_HELP_COSH:
|
|
HELP(help_cosh);
|
|
break;
|
|
case ID_HELP_SINH:
|
|
HELP(help_sinh);
|
|
break;
|
|
case ID_HELP_TANH:
|
|
HELP(help_tanh);
|
|
break;
|
|
|
|
// special functions
|
|
|
|
case ID_HELP_BESSELJ:
|
|
HELP(help_besselj);
|
|
break;
|
|
case ID_HELP_HERMITE:
|
|
HELP(help_hermite);
|
|
break;
|
|
case ID_HELP_LAGUERRE:
|
|
HELP(help_laguerre);
|
|
break;
|
|
case ID_HELP_LEGENDRE:
|
|
HELP(help_legendre);
|
|
break;
|
|
|
|
// polynomial functions
|
|
|
|
case ID_HELP_COEFF:
|
|
HELP(help_coeff);
|
|
break;
|
|
case ID_HELP_DEG:
|
|
HELP(help_deg);
|
|
break;
|
|
case ID_HELP_QUOTIENT:
|
|
HELP(help_quotient);
|
|
break;
|
|
|
|
// other functions
|
|
|
|
case ID_HELP_ABS:
|
|
HELP(help_abs);
|
|
break;
|
|
case ID_HELP_CHOOSE:
|
|
HELP(help_choose);
|
|
break;
|
|
case ID_HELP_CIRCEXP:
|
|
HELP(help_circexp);
|
|
break;
|
|
case ID_HELP_DENOMINATOR:
|
|
HELP(help_denominator);
|
|
break;
|
|
case ID_HELP_ERF:
|
|
HELP(help_erf);
|
|
break;
|
|
case ID_HELP_ERFC:
|
|
HELP(help_erfc);
|
|
break;
|
|
case ID_HELP_EVAL:
|
|
HELP(help_eval);
|
|
break;
|
|
case ID_HELP_EXP:
|
|
HELP(help_exp);
|
|
break;
|
|
case ID_HELP_EXPCOS:
|
|
HELP(help_expcos);
|
|
break;
|
|
case ID_HELP_EXPSIN:
|
|
HELP(help_expsin);
|
|
break;
|
|
case ID_HELP_FACTOR:
|
|
HELP(help_factor);
|
|
break;
|
|
case ID_HELP_FACTORIAL:
|
|
HELP(help_factorial);
|
|
break;
|
|
case ID_HELP_FOR:
|
|
HELP(help_for);
|
|
break;
|
|
case ID_HELP_LOG:
|
|
HELP(help_log);
|
|
break;
|
|
case ID_HELP_NUMERATOR:
|
|
HELP(help_numerator);
|
|
break;
|
|
case ID_HELP_PRODUCT:
|
|
HELP(help_product);
|
|
break;
|
|
case ID_HELP_SQRT:
|
|
HELP(help_sqrt);
|
|
break;
|
|
case ID_HELP_SUM:
|
|
HELP(help_sum);
|
|
break;
|
|
case ID_HELP_TAYLOR:
|
|
HELP(help_taylor);
|
|
break;
|
|
|
|
// window buttons, clear, draw, etc.
|
|
|
|
case ID_CLEAR:
|
|
do_button("clear");
|
|
break;
|
|
case ID_DRAW:
|
|
do_button("draw");
|
|
break;
|
|
case ID_SIMPLIFY:
|
|
do_button("simplify");
|
|
break;
|
|
case ID_FLOAT:
|
|
do_button("float");
|
|
break;
|
|
case ID_DERIVATIVE:
|
|
do_button("derivative");
|
|
break;
|
|
case ID_INTEGRAL:
|
|
do_button("integral");
|
|
break;
|
|
case ID_EDIT_SCRIPT:
|
|
if (running)
|
|
break;
|
|
if (edit_mode == 0)
|
|
goto_edit_mode();
|
|
else
|
|
goto_calc_mode();
|
|
break;
|
|
case ID_RUN_SCRIPT:
|
|
run_script();
|
|
break;
|
|
|
|
default:
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
}
|
|
break;
|
|
case WM_PAINT:
|
|
draw_hdc = BeginPaint(hWnd, &ps);
|
|
if (edit_mode == 0) {
|
|
SetBkMode(draw_hdc, TRANSPARENT);
|
|
draw_display();
|
|
update_scroll_bars();
|
|
}
|
|
// paint the little square between the scroll bars
|
|
r.left = display_width;
|
|
r.top = display_height;
|
|
r.right = r.left + scroll_bar_width + 1;
|
|
r.bottom = r.top + scroll_bar_width + 1;
|
|
FillRect(draw_hdc, &r, (HBRUSH) (COLOR_BTNFACE + 1));
|
|
EndPaint(hWnd, &ps);
|
|
break;
|
|
case WM_DESTROY:
|
|
PostQuitMessage(0);
|
|
break;
|
|
case WM_VSCROLL:
|
|
if ((HWND) lParam == vscroll)
|
|
do_vscroll(LOWORD(wParam), HIWORD(wParam));
|
|
else
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
break;
|
|
case WM_HSCROLL:
|
|
if ((HWND) lParam == hscroll)
|
|
do_hscroll(LOWORD(wParam), HIWORD(wParam));
|
|
else
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
break;
|
|
case WM_KEYDOWN:
|
|
if (edit_mode == 0)
|
|
switch (wParam) {
|
|
case VK_PRIOR:
|
|
SendMessage(
|
|
main_window,
|
|
WM_VSCROLL,
|
|
MAKELONG(SB_PAGEUP, 0),
|
|
(LPARAM) vscroll);
|
|
break;
|
|
case VK_NEXT:
|
|
SendMessage(
|
|
main_window,
|
|
WM_VSCROLL,
|
|
MAKELONG(SB_PAGEDOWN, 0),
|
|
(LPARAM) vscroll);
|
|
break;
|
|
default:
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
}
|
|
else
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
break;
|
|
default:
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
char *
|
|
get_curr_cmd(void)
|
|
{
|
|
int i, len;
|
|
char *s;
|
|
|
|
len = GetWindowTextLength(input_window);
|
|
s = (char *) malloc(len + 1);
|
|
GetWindowText(input_window, s, len + 1);
|
|
|
|
// trim trailing spaces
|
|
|
|
for (i = len - 1; i >= 0; i--) {
|
|
if (isspace(s[i]))
|
|
s[i] = 0;
|
|
else
|
|
break;
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
void
|
|
update_curr_cmd(char *s)
|
|
{
|
|
SetWindowText(input_window, s);
|
|
}
|
|
|
|
void
|
|
do_fonts(void)
|
|
{
|
|
static LOGFONT lf;
|
|
|
|
lf.lfQuality = ANTIALIASED_QUALITY;
|
|
lf.lfPitchAndFamily = FF_ROMAN + VARIABLE_PITCH;
|
|
|
|
lf.lfHeight = 36;
|
|
|
|
lf.lfItalic = FALSE;
|
|
lf.lfCharSet = ANSI_CHARSET;
|
|
strcpy(lf.lfFaceName, "Times");
|
|
display_font[TIMES_FONT] = CreateFontIndirect(&lf);
|
|
|
|
lf.lfItalic = TRUE;
|
|
lf.lfCharSet = ANSI_CHARSET;
|
|
strcpy(lf.lfFaceName, "Times");
|
|
display_font[ITALIC_TIMES_FONT] = CreateFontIndirect(&lf);
|
|
|
|
lf.lfItalic = FALSE;
|
|
lf.lfCharSet = SYMBOL_CHARSET;
|
|
strcpy(lf.lfFaceName, "Symbol");
|
|
display_font[SYMBOL_FONT] = CreateFontIndirect(&lf);
|
|
|
|
lf.lfItalic = TRUE;
|
|
lf.lfCharSet = SYMBOL_CHARSET;
|
|
strcpy(lf.lfFaceName, "Symbol");
|
|
display_font[ITALIC_SYMBOL_FONT] = CreateFontIndirect(&lf);
|
|
|
|
lf.lfHeight = 24;
|
|
|
|
lf.lfItalic = FALSE;
|
|
lf.lfCharSet = ANSI_CHARSET;
|
|
strcpy(lf.lfFaceName, "Times");
|
|
display_font[SMALL_TIMES_FONT] = CreateFontIndirect(&lf);
|
|
|
|
lf.lfItalic = TRUE;
|
|
lf.lfCharSet = ANSI_CHARSET;
|
|
strcpy(lf.lfFaceName, "Times");
|
|
display_font[SMALL_ITALIC_TIMES_FONT] = CreateFontIndirect(&lf);
|
|
|
|
lf.lfItalic = FALSE;
|
|
lf.lfCharSet = SYMBOL_CHARSET;
|
|
strcpy(lf.lfFaceName, "Symbol");
|
|
display_font[SMALL_SYMBOL_FONT] = CreateFontIndirect(&lf);
|
|
|
|
lf.lfItalic = TRUE;
|
|
lf.lfCharSet = SYMBOL_CHARSET;
|
|
strcpy(lf.lfFaceName, "Symbol");
|
|
display_font[SMALL_ITALIC_SYMBOL_FONT] = CreateFontIndirect(&lf);
|
|
|
|
// DEFAULT_FONT
|
|
|
|
lf.lfHeight = 20;
|
|
lf.lfItalic = FALSE;
|
|
lf.lfWeight = FW_BOLD;
|
|
lf.lfCharSet = ANSI_CHARSET;
|
|
lf.lfQuality = ANTIALIASED_QUALITY;
|
|
lf.lfPitchAndFamily = FF_MODERN;
|
|
strcpy(lf.lfFaceName, "");
|
|
display_font[DEFAULT_FONT] = CreateFontIndirect(&lf);
|
|
|
|
// SMALL_FONT
|
|
|
|
display_font[SMALL_FONT] = (HFONT) GetStockObject(ANSI_FIXED_FONT);
|
|
}
|
|
|
|
void
|
|
fill_font_metric_array(void)
|
|
{
|
|
int i;
|
|
HDC hdc;
|
|
TEXTMETRIC tm;
|
|
|
|
hdc = GetDC(main_window);
|
|
|
|
for (i = 1; i < NFONT; i++) {
|
|
|
|
SelectObject(hdc, display_font[i]);
|
|
GetTextMetrics(hdc, &tm);
|
|
|
|
text_metric[i].ascent = tm.tmAscent;
|
|
text_metric[i].descent = tm.tmDescent;
|
|
text_metric[i].width = tm.tmAveCharWidth;
|
|
}
|
|
|
|
ReleaseDC(main_window, hdc);
|
|
}
|
|
|
|
static void
|
|
goto_edit_mode(void)
|
|
{
|
|
int i;
|
|
|
|
if (edit_mode == 1)
|
|
return;
|
|
|
|
edit_mode = 1;
|
|
|
|
// dim buttons
|
|
|
|
for (i = 0; i < NBUTTON - 2; i++)
|
|
EnableWindow(button[i], FALSE);
|
|
|
|
SendMessage(button[NBUTTON - 2], WM_SETTEXT, 0, (LPARAM) "<<");
|
|
|
|
ShowWindow(input_window, SW_HIDE);
|
|
ShowWindow(vscroll, SW_HIDE);
|
|
ShowWindow(hscroll, SW_HIDE);
|
|
ShowWindow(edit_window, SW_SHOW);
|
|
SetFocus(edit_window);
|
|
}
|
|
|
|
static void
|
|
goto_calc_mode(void)
|
|
{
|
|
int i;
|
|
|
|
if (edit_mode == 0)
|
|
return;
|
|
|
|
edit_mode = 0;
|
|
|
|
// light buttons
|
|
|
|
for (i = 0; i < NBUTTON - 2; i++)
|
|
EnableWindow(button[i], TRUE);
|
|
|
|
SendMessage(button[NBUTTON - 2], WM_SETTEXT, 0, (LPARAM) "Edit Script");
|
|
|
|
ShowWindow(edit_window, SW_HIDE);
|
|
ShowWindow(input_window, SW_SHOW);
|
|
ShowWindow(vscroll, SW_SHOW);
|
|
ShowWindow(hscroll, SW_SHOW);
|
|
SetFocus(input_window);
|
|
}
|
|
|
|
// TextOut can only handle 4,000 or so chars at a time
|
|
|
|
void
|
|
draw_text(int font, int x, int y, char *s, int len)
|
|
{
|
|
SelectObject(draw_hdc, display_font[font]);
|
|
TextOut(draw_hdc, x, y, s, len);
|
|
#if 0
|
|
SIZE size;
|
|
SelectObject(draw_hdc, display_font[font]);
|
|
while (len > 4000) {
|
|
TextOut(hdc, x, y, s, 4000);
|
|
GetTextExtentPoint32(hdc, s, 4000, &size);
|
|
x += size.cx;
|
|
s += 4000;
|
|
len -= 4000;
|
|
}
|
|
if (len)
|
|
TextOut(draw_hdc, x, y, (char *) s, len);
|
|
#endif
|
|
}
|
|
|
|
int
|
|
text_width(int font, char *s)
|
|
{
|
|
SIZE size;
|
|
SelectObject(run_hdc, display_font[font]);
|
|
GetTextExtentPoint32(run_hdc, s, (int) strlen(s), &size);
|
|
return (int) size.cx;
|
|
}
|
|
|
|
void
|
|
get_height_width(int *h, int *w, int font, char *s)
|
|
{
|
|
SIZE size;
|
|
SelectObject(run_hdc, display_font[font]);
|
|
GetTextExtentPoint32(run_hdc, s, (int) strlen(s), &size);
|
|
*h = size.cy;
|
|
*w = size.cx;
|
|
}
|
|
|
|
void
|
|
draw_hrule(int x, int y, int w)
|
|
{
|
|
MoveToEx(draw_hdc, x, y, NULL);
|
|
LineTo(draw_hdc, x + w, y);
|
|
}
|
|
|
|
// Example: w = 5, h = 7
|
|
//
|
|
// 0 1 2 3 4
|
|
// 0 B x x x A
|
|
// 1 x
|
|
// 2 x
|
|
// 3 x
|
|
// 4 x
|
|
// 5 x
|
|
// 6 C x x x D
|
|
//
|
|
// A = (x + w - 1, y)
|
|
//
|
|
// B = (x, y)
|
|
//
|
|
// C = (x, y + h - 1)
|
|
//
|
|
// D = (x + w - 1, y + h - 1)
|
|
//
|
|
// Since the last pixel is not drawn, use D = (x + w, y + h - 1).
|
|
|
|
void
|
|
draw_left_bracket(int x, int y, int w, int h)
|
|
{
|
|
MoveToEx(draw_hdc, x + w - 1, y, NULL);
|
|
LineTo(draw_hdc, x, y);
|
|
LineTo(draw_hdc, x, y + h - 1);
|
|
LineTo(draw_hdc, x + w, y + h - 1);
|
|
|
|
// extra stem width
|
|
|
|
MoveToEx(draw_hdc, x + 1, y, NULL);
|
|
LineTo(draw_hdc, x + 1, y + h - 1);
|
|
}
|
|
|
|
// Example: w = 5, h = 7
|
|
//
|
|
// 0 1 2 3 4
|
|
// 0 A x x x B
|
|
// 1 x
|
|
// 2 x
|
|
// 3 x
|
|
// 4 x
|
|
// 5 x
|
|
// 6 D x x x C
|
|
//
|
|
// A = (x, y)
|
|
//
|
|
// B = (x + w - 1, y)
|
|
//
|
|
// C = (x + w - 1, y + h - 1)
|
|
//
|
|
// D = (x, y + h - 1)
|
|
//
|
|
// Since the last pixel is not drawn, use D = (x - 1, y + h - 1).
|
|
|
|
void
|
|
draw_right_bracket(int x, int y, int w, int h)
|
|
{
|
|
MoveToEx(draw_hdc, x, y, NULL);
|
|
LineTo(draw_hdc, x + w - 1, y);
|
|
LineTo(draw_hdc, x + w - 1, y + h - 1);
|
|
LineTo(draw_hdc, x - 1, y + h - 1);
|
|
|
|
// extra stem width
|
|
|
|
MoveToEx(draw_hdc, x + w - 2, y, NULL);
|
|
LineTo(draw_hdc, x + w - 2, y + h - 1);
|
|
}
|
|
|
|
void
|
|
draw_line(int x1, int y1, int x2, int y2)
|
|
{
|
|
MoveToEx(draw_hdc, x1, y1, NULL);
|
|
LineTo(draw_hdc, x2, y2);
|
|
}
|
|
|
|
static int draw_mode;
|
|
static HPEN original_pen;
|
|
static HBRUSH original_brush;
|
|
|
|
void
|
|
use_graph_pen(void)
|
|
{
|
|
HPEN pen;
|
|
HBRUSH brush;
|
|
LOGBRUSH tmp;
|
|
if (draw_mode == 1)
|
|
return;
|
|
draw_mode = 1;
|
|
pen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
|
|
tmp.lbStyle = BS_SOLID;
|
|
tmp.lbColor = RGB(0, 0, 0);
|
|
tmp.lbHatch = 0;
|
|
brush = CreateBrushIndirect(&tmp);
|
|
original_pen = (HPEN) SelectObject(draw_hdc, pen);
|
|
original_brush = (HBRUSH) SelectObject(draw_hdc, brush);
|
|
}
|
|
|
|
void
|
|
use_normal_pen(void)
|
|
{
|
|
HPEN pen;
|
|
HBRUSH brush;
|
|
if (draw_mode == 0)
|
|
return;
|
|
draw_mode = 0;
|
|
pen = (HPEN) SelectObject(draw_hdc, original_pen);
|
|
brush = (HBRUSH) SelectObject(draw_hdc, original_brush);
|
|
DeleteObject(pen);
|
|
DeleteObject(brush);
|
|
}
|
|
|
|
void
|
|
draw_box(int x1, int y1, int x2, int y2)
|
|
{
|
|
#if 1
|
|
HBRUSH brush;
|
|
LOGBRUSH tmp;
|
|
use_normal_pen();
|
|
tmp.lbStyle = BS_SOLID;
|
|
tmp.lbColor = RGB(255, 255, 239);
|
|
tmp.lbHatch = 0;
|
|
brush = CreateBrushIndirect(&tmp);
|
|
SelectObject(draw_hdc, brush);
|
|
Rectangle(draw_hdc, x1, y1, x2 + 1, y2 + 1);
|
|
brush = (HBRUSH) GetStockObject(WHITE_BRUSH);
|
|
brush = (HBRUSH) SelectObject(draw_hdc, brush);
|
|
DeleteObject(brush);
|
|
#else
|
|
MoveToEx(draw_hdc, x1, y1, NULL);
|
|
LineTo(draw_hdc, x2, y1);
|
|
LineTo(draw_hdc, x2, y2);
|
|
LineTo(draw_hdc, x1, y2);
|
|
LineTo(draw_hdc, x1, y1);
|
|
#endif
|
|
}
|
|
|
|
void
|
|
draw_point(int x, int dx, int y, int dy)
|
|
{
|
|
//Rectangle(draw_hdc, x - 1, y - 1, x + 2, y + 2);
|
|
RECT r;
|
|
r.left = x + dx - 1;
|
|
r.top = y + dy - 1;
|
|
r.right = x + dx + 2;
|
|
r.bottom = y + dy + 2;
|
|
if (dx == 0)
|
|
r.left++;
|
|
if (dy == 0)
|
|
r.top++;
|
|
if (dx == 300)
|
|
r.right--;
|
|
if (dy == 300)
|
|
r.bottom--;
|
|
FillRect(draw_hdc, &r, (HBRUSH) GetStockObject(BLACK_BRUSH));
|
|
}
|
|
|
|
static void
|
|
move_input_window(void)
|
|
{
|
|
int h, w, x, y;
|
|
|
|
x = 0;
|
|
y = main_client_height - 3 * line_height;
|
|
w = main_client_width;
|
|
h = line_height;
|
|
|
|
MoveWindow(input_window, x, y, w, h, TRUE);
|
|
}
|
|
|
|
static void
|
|
move_edit_window(void)
|
|
{
|
|
int h, w, x, y;
|
|
|
|
x = 0;
|
|
y = 0;
|
|
w = main_client_width;
|
|
h = main_client_height - 2 * line_height;
|
|
|
|
MoveWindow(edit_window, x, y, w, h, TRUE);
|
|
}
|
|
|
|
static void
|
|
move_buttons(void)
|
|
{
|
|
int i, j, k;
|
|
for (i = 0; i < NBUTTON; i++) {
|
|
j = i * main_client_width / NBUTTON;
|
|
k = (i + 1) * main_client_width / NBUTTON;
|
|
MoveWindow(
|
|
button[i],
|
|
j, main_client_height - 2 * line_height,
|
|
k - j, 2 * line_height,
|
|
TRUE);
|
|
}
|
|
}
|
|
|
|
static void
|
|
move_scroll_bars(void)
|
|
{
|
|
int h, w, x, y;
|
|
|
|
x = display_width;
|
|
y = 0;
|
|
w = scroll_bar_width,
|
|
h = display_height;
|
|
|
|
MoveWindow(vscroll, x, y, w, h, TRUE);
|
|
|
|
x = 0;
|
|
y = display_height;
|
|
w = display_width;
|
|
h = scroll_bar_width;
|
|
|
|
MoveWindow(hscroll, x, y, w, h, TRUE);
|
|
}
|
|
|
|
// Cannot use "pos" because it is too small (16 bits). Use GetScrollInfo instead.
|
|
|
|
static void
|
|
do_vscroll(int cmd, int pos)
|
|
{
|
|
int y;
|
|
SCROLLINFO info;
|
|
|
|
y = display_y;
|
|
|
|
switch (cmd) {
|
|
|
|
case SB_TOP:
|
|
display_y = 0;
|
|
break;
|
|
|
|
case SB_BOTTOM:
|
|
display_y = max_y;
|
|
break;
|
|
|
|
case SB_LINEUP:
|
|
display_y -= line_height;
|
|
break;
|
|
|
|
case SB_LINEDOWN:
|
|
display_y += line_height;
|
|
break;
|
|
|
|
case SB_PAGEUP:
|
|
display_y -= display_height;
|
|
break;
|
|
|
|
case SB_PAGEDOWN:
|
|
display_y += display_height;
|
|
break;
|
|
|
|
case SB_THUMBTRACK:
|
|
case SB_THUMBPOSITION:
|
|
info.cbSize = sizeof (SCROLLINFO);
|
|
info.fMask = SIF_TRACKPOS;
|
|
GetScrollInfo(vscroll, SB_CTL, &info);
|
|
display_y = info.nTrackPos;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (display_y < 0)
|
|
display_y = 0;
|
|
|
|
if (display_y > max_y)
|
|
display_y = max_y;
|
|
|
|
if (display_y < y)
|
|
move_bits_down(y - display_y);
|
|
|
|
if (display_y > y)
|
|
move_bits_up(display_y - y);
|
|
|
|
update_scroll_bars();
|
|
}
|
|
|
|
static void
|
|
move_bits_down(int dy)
|
|
{
|
|
RECT r;
|
|
HRGN hrgn;
|
|
|
|
//ScrollWindowEx(main_window, 0, dy, NULL, NULL, NULL, NULL, SW_ERASE | SW_INVALIDATE);
|
|
//return;
|
|
|
|
draw_hdc = GetDC(main_window);
|
|
|
|
if (dy < display_height)
|
|
BitBlt(
|
|
draw_hdc,
|
|
0, dy,
|
|
display_width, display_height - dy,
|
|
draw_hdc,
|
|
0, 0,
|
|
SRCCOPY);
|
|
else
|
|
dy = display_height;
|
|
|
|
r.left = 0;
|
|
r.top = 0;
|
|
r.right = display_width;
|
|
r.bottom = dy;
|
|
|
|
// have to draw instead of update to stay ahead of next scroll event
|
|
|
|
// display bitmap has to be valid before next scroll event
|
|
|
|
FillRect(draw_hdc, &r, (HBRUSH) GetStockObject(WHITE_BRUSH));
|
|
hrgn = CreateRectRgnIndirect(&r);
|
|
SelectClipRgn(draw_hdc, hrgn);
|
|
SetBkMode(draw_hdc, TRANSPARENT);
|
|
draw_display();
|
|
DeleteObject(hrgn);
|
|
|
|
ReleaseDC(main_window, draw_hdc);
|
|
}
|
|
|
|
static void
|
|
move_bits_up(int dy)
|
|
{
|
|
RECT r;
|
|
HRGN hrgn;
|
|
|
|
//ScrollWindowEx(main_window, 0, -dy, NULL, NULL, NULL, NULL, SW_ERASE | SW_INVALIDATE);
|
|
//return;
|
|
|
|
draw_hdc = GetDC(main_window);
|
|
|
|
if (dy < display_height)
|
|
BitBlt(
|
|
draw_hdc,
|
|
0, 0,
|
|
display_width, display_height - dy,
|
|
draw_hdc,
|
|
0, dy,
|
|
SRCCOPY);
|
|
else
|
|
dy = display_height;
|
|
|
|
r.left = 0;
|
|
r.top = display_height - dy;
|
|
r.right = display_width;
|
|
r.bottom = display_height;
|
|
|
|
// have to draw instead of update to stay ahead of next scroll event
|
|
|
|
// display bitmap has to be valid before next scroll event
|
|
|
|
FillRect(draw_hdc, &r, (HBRUSH) GetStockObject(WHITE_BRUSH));
|
|
hrgn = CreateRectRgnIndirect(&r);
|
|
SelectClipRgn(draw_hdc, hrgn);
|
|
SetBkMode(draw_hdc, TRANSPARENT);
|
|
draw_display();
|
|
DeleteObject(hrgn);
|
|
|
|
ReleaseDC(main_window, draw_hdc);
|
|
}
|
|
|
|
// According to MS documentation...
|
|
//
|
|
// MaxScrollPos = MaxRangeValue - (PageSize - 1)
|
|
//
|
|
// Since we want MaxScrollPos = max_y, we set nMax = max_y + display_height - 1.
|
|
//
|
|
// nMax = max_y + display_height - 1
|
|
//
|
|
// nPage = display_height
|
|
//
|
|
// MaxScrollPos = max_y + display_height - 1 - (display_height - 1) = max_y
|
|
|
|
static void
|
|
update_scroll_bars(void)
|
|
{
|
|
SCROLLINFO info;
|
|
|
|
info.cbSize = sizeof (SCROLLINFO);
|
|
info.fMask = SIF_ALL;
|
|
info.nMin = 0;
|
|
info.nMax = max_y + display_height - 1;
|
|
info.nPage = display_height;
|
|
info.nPos = display_y;
|
|
SetScrollInfo(vscroll, SB_CTL, &info, TRUE);
|
|
|
|
info.cbSize = sizeof (SCROLLINFO);
|
|
info.fMask = SIF_ALL;
|
|
info.nMin = 0;
|
|
info.nMax = max_x + display_width - 1;
|
|
info.nPage = display_width;
|
|
info.nPos = display_x;
|
|
SetScrollInfo(hscroll, SB_CTL, &info, TRUE);
|
|
}
|
|
|
|
// Cannot use "pos" because it is too small (16 bits). Use GetScrollInfo instead.
|
|
|
|
static void move_bits_left(int);
|
|
static void move_bits_right(int);
|
|
|
|
void
|
|
do_hscroll(int cmd, int pos)
|
|
{
|
|
int x;
|
|
SCROLLINFO info;
|
|
|
|
x = display_x;
|
|
|
|
switch (cmd) {
|
|
|
|
case SB_LEFT:
|
|
display_x = 0;
|
|
break;
|
|
|
|
case SB_RIGHT:
|
|
display_x = max_x;
|
|
break;
|
|
|
|
case SB_LINELEFT:
|
|
display_x -= line_height;
|
|
break;
|
|
|
|
case SB_LINERIGHT:
|
|
display_x += line_height;
|
|
break;
|
|
|
|
case SB_PAGELEFT:
|
|
display_x -= display_width;
|
|
break;
|
|
|
|
case SB_PAGERIGHT:
|
|
display_x += display_width;
|
|
break;
|
|
|
|
case SB_THUMBTRACK:
|
|
case SB_THUMBPOSITION:
|
|
info.cbSize = sizeof (SCROLLINFO);
|
|
info.fMask = SIF_TRACKPOS;
|
|
GetScrollInfo(hscroll, SB_CTL, &info);
|
|
display_x = info.nTrackPos;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (display_x < 0)
|
|
display_x = 0;
|
|
|
|
if (display_x > max_x)
|
|
display_x = max_x;
|
|
|
|
if (display_x < x)
|
|
move_bits_right(x - display_x);
|
|
|
|
if (display_x > x)
|
|
move_bits_left(display_x - x);
|
|
|
|
update_scroll_bars();
|
|
}
|
|
|
|
static void
|
|
move_bits_right(int dx)
|
|
{
|
|
int h, w, x, y;
|
|
RECT r;
|
|
HRGN hrgn;
|
|
|
|
draw_hdc = GetDC(main_window);
|
|
|
|
if (dx < display_width) {
|
|
|
|
// Example: dx = 2
|
|
//
|
|
// x x x x x x x x x x
|
|
// x x x
|
|
// x x x
|
|
// x x x
|
|
// x x x
|
|
// x x x x x x x x x x
|
|
// \ \
|
|
// \ \
|
|
// \ \
|
|
// \ \
|
|
// x x x x x x x x x x
|
|
// x x x
|
|
// x x x
|
|
// x x x
|
|
// x x x
|
|
// x x x x x x x x x x
|
|
|
|
// dimensions of dst rectangle
|
|
|
|
x = dx;
|
|
y = 0;
|
|
w = display_width - dx;
|
|
h = display_height;
|
|
|
|
BitBlt(
|
|
draw_hdc,
|
|
x, y,
|
|
w, h,
|
|
draw_hdc,
|
|
0, 0, // src
|
|
SRCCOPY);
|
|
} else
|
|
dx = display_width;
|
|
|
|
// set update rectangle
|
|
|
|
if (dx == 1) dx = 2; // bug in windows 2000
|
|
|
|
r.left = 0;
|
|
r.top = 0;
|
|
r.right = dx;
|
|
r.bottom = display_height;
|
|
|
|
// have to draw instead of update to stay ahead of next scroll event
|
|
|
|
// display bitmap has to be valid before next scroll event
|
|
|
|
FillRect(draw_hdc, &r, (HBRUSH) GetStockObject(WHITE_BRUSH));
|
|
hrgn = CreateRectRgnIndirect(&r);
|
|
SelectClipRgn(draw_hdc, hrgn);
|
|
SetBkMode(draw_hdc, TRANSPARENT);
|
|
draw_display();
|
|
DeleteObject(hrgn);
|
|
|
|
ReleaseDC(main_window, draw_hdc);
|
|
}
|
|
|
|
static void
|
|
move_bits_left(int dx)
|
|
{
|
|
int h, w, x, y;
|
|
RECT r;
|
|
HRGN hrgn;
|
|
|
|
draw_hdc = GetDC(main_window);
|
|
|
|
if (dx < display_width) {
|
|
|
|
// Example: dx = 2
|
|
//
|
|
// x x x x x x x x x x
|
|
// x x x
|
|
// x x x
|
|
// x x x
|
|
// x x x
|
|
// x x x x x x x x x x
|
|
// / /
|
|
// / /
|
|
// / /
|
|
// / /
|
|
// x x x x x x x x x x
|
|
// x x x
|
|
// x x x
|
|
// x x x
|
|
// x x x
|
|
// x x x x x x x x x x
|
|
|
|
// dimensions of dst rectangle
|
|
|
|
x = 0;
|
|
y = 0;
|
|
w = display_width - dx;
|
|
h = display_height;
|
|
|
|
BitBlt(
|
|
draw_hdc,
|
|
x, y,
|
|
w, h,
|
|
draw_hdc,
|
|
dx, 0, // src
|
|
SRCCOPY);
|
|
} else
|
|
dx = display_width;
|
|
|
|
// set update rectangle
|
|
|
|
if (dx == 1) dx = 2; // bug in windows 2000
|
|
|
|
r.left = display_width - dx;
|
|
r.top = 0;
|
|
r.right = display_width;
|
|
r.bottom = display_height;
|
|
|
|
// have to draw instead of update to stay ahead of next scroll event
|
|
|
|
// display bitmap has to be valid before next scroll event
|
|
|
|
FillRect(draw_hdc, &r, (HBRUSH) GetStockObject(WHITE_BRUSH));
|
|
hrgn = CreateRectRgnIndirect(&r);
|
|
SelectClipRgn(draw_hdc, hrgn);
|
|
SetBkMode(draw_hdc, TRANSPARENT);
|
|
draw_display();
|
|
DeleteObject(hrgn);
|
|
|
|
ReleaseDC(main_window, draw_hdc);
|
|
}
|
|
|
|
#if 0
|
|
|
|
void
|
|
redraw_window_now(void)
|
|
{
|
|
RECT r;
|
|
HRGN hrgn;
|
|
|
|
draw_hdc = GetDC(main_window);
|
|
|
|
r.left = 0;
|
|
r.top = 0;
|
|
r.right = display_width;
|
|
r.bottom = display_height;
|
|
|
|
FillRect(draw_hdc, &r, (HBRUSH) GetStockObject(WHITE_BRUSH));
|
|
hrgn = CreateRectRgnIndirect(&r);
|
|
SelectClipRgn(draw_hdc, hrgn);
|
|
SetBkMode(draw_hdc, TRANSPARENT);
|
|
draw_display();
|
|
DeleteObject(hrgn);
|
|
|
|
ReleaseDC(main_window, draw_hdc);
|
|
|
|
update_scroll_bars();
|
|
|
|
SetFocus(input_window);
|
|
}
|
|
|
|
#endif
|
|
|
|
void
|
|
update_display(void)
|
|
{
|
|
RECT r;
|
|
if (update_display_request == 0)
|
|
return;
|
|
r.left = 0;
|
|
r.top = 0;
|
|
r.right = display_width;
|
|
r.bottom = display_height;
|
|
RedrawWindow(main_window, &r, NULL, RDW_ERASE | RDW_INVALIDATE);
|
|
}
|
|
|
|
OPENFILENAME ofn;
|
|
char filename[1000];
|
|
|
|
// f = fopen(s, "rb"); // must do rb for msdos files else \r changes to \n
|
|
|
|
static void
|
|
do_create_script(void)
|
|
{
|
|
char *s;
|
|
*filename = 0;
|
|
s = get_cmd_history();
|
|
SetWindowText(edit_window, s);
|
|
free(s);
|
|
goto_edit_mode();
|
|
}
|
|
|
|
static void
|
|
do_new(void)
|
|
{
|
|
char buf[1];
|
|
*filename = 0;
|
|
buf[0] = 0;
|
|
SetWindowText(edit_window, buf);
|
|
goto_edit_mode();
|
|
}
|
|
|
|
static void
|
|
do_open(void)
|
|
{
|
|
int len;
|
|
FILE *f;
|
|
char *buf;
|
|
ofn.lStructSize = sizeof (OPENFILENAME);
|
|
ofn.hwndOwner = main_window;
|
|
ofn.lpstrFile = filename;
|
|
ofn.nMaxFile = 1000;
|
|
if (GetOpenFileName(&ofn) == 0)
|
|
return;
|
|
buf = (char *) malloc(100001);
|
|
if (buf == 0)
|
|
return;
|
|
f = fopen(filename, "rb"); // must do rb for msdos files else \r changes to \n
|
|
if (f == 0) {
|
|
free(buf);
|
|
return;
|
|
}
|
|
len = (int) fread(buf, 1, 100000, f);
|
|
fclose(f);
|
|
buf[len] = 0;
|
|
SetWindowText(edit_window, buf);
|
|
free(buf);
|
|
goto_edit_mode();
|
|
}
|
|
|
|
static void
|
|
do_save(void)
|
|
{
|
|
if (*filename)
|
|
save_file();
|
|
else
|
|
do_saveas();
|
|
}
|
|
|
|
static void
|
|
do_saveas(void)
|
|
{
|
|
ofn.lStructSize = sizeof (OPENFILENAME);
|
|
ofn.hwndOwner = main_window;
|
|
ofn.lpstrFile = filename;
|
|
ofn.nMaxFile = 1000;
|
|
if (GetSaveFileName(&ofn) == 0)
|
|
return;
|
|
save_file();
|
|
}
|
|
|
|
static void
|
|
save_file(void)
|
|
{
|
|
int len;
|
|
FILE *f;
|
|
char *buf;
|
|
len = GetWindowTextLength(edit_window);
|
|
buf = (char *) malloc(len + 1);
|
|
if (buf == 0) {
|
|
printstr("Error writing file.\n");
|
|
update_display();
|
|
return;
|
|
}
|
|
GetWindowText(edit_window, buf, len + 1);
|
|
f = fopen(filename, "wb");
|
|
if (f == NULL) {
|
|
free(buf);
|
|
printstr("Error writing file.\n");
|
|
update_display();
|
|
return;
|
|
}
|
|
if (fwrite(buf, 1, len, f) != len) {
|
|
printstr("Error writing file.\n");
|
|
update_display();
|
|
}
|
|
fclose(f);
|
|
free(buf);
|
|
}
|
|
|
|
PAGESETUPDLG page;
|
|
|
|
static void
|
|
do_page_setup(void)
|
|
{
|
|
page.lStructSize = sizeof page;
|
|
page.hwndOwner = main_window;
|
|
|
|
PageSetupDlg(&page);
|
|
}
|
|
|
|
PRINTDLG pd;
|
|
|
|
static void
|
|
do_print(void)
|
|
{
|
|
if (pd.lStructSize == 0) {
|
|
pd.lStructSize = sizeof pd;
|
|
pd.hwndOwner = main_window;
|
|
pd.hDevMode = NULL;
|
|
pd.hDevNames = NULL;
|
|
pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
|
|
pd.nCopies = 1;
|
|
pd.nFromPage = 1;
|
|
pd.nToPage = 1;
|
|
pd.nMinPage = 1;
|
|
pd.nMaxPage = 0xffff;
|
|
}
|
|
|
|
if (PrintDlg(&pd) == TRUE) {
|
|
|
|
|
|
DeleteDC(pd.hDC);
|
|
}
|
|
}
|
|
|
|
static char *inp;
|
|
static HANDLE thread;
|
|
|
|
static DWORD WINAPI
|
|
task(LPVOID p)
|
|
{
|
|
run_hdc = GetDC(main_window);
|
|
run(inp);
|
|
ReleaseDC(main_window, run_hdc);
|
|
running = 2;
|
|
send_user_event();
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
create_task(void)
|
|
{
|
|
DWORD id;
|
|
timer = (unsigned int) time(NULL);
|
|
running = 1;
|
|
thread = CreateThread(
|
|
NULL,
|
|
1024 * 1024,
|
|
task,
|
|
NULL,
|
|
0,
|
|
&id);
|
|
}
|
|
|
|
static void
|
|
send_user_event(void)
|
|
{
|
|
PostMessage(main_window, ID_USER_EVENT, 0, 0);
|
|
}
|
|
|
|
static void
|
|
process_user_event(void)
|
|
{
|
|
unsigned int dt;
|
|
static char buf[1000];
|
|
|
|
if (running == 0)
|
|
return;
|
|
|
|
if (running == 2) {
|
|
CloseHandle(thread);
|
|
update_curr_cmd("");
|
|
update_display();
|
|
activate_controls();
|
|
running = 0;
|
|
return;
|
|
}
|
|
|
|
dt = (unsigned int) time(NULL) - timer;
|
|
|
|
if (dt > 1) {
|
|
deactivate_controls();
|
|
sprintf(buf, "Working on it for %d seconds. Esc might interrupt, otherwise close this window to quit.", dt);
|
|
update_curr_cmd(buf);
|
|
update_display();
|
|
}
|
|
}
|
|
|
|
static int shunted;
|
|
|
|
static void
|
|
deactivate_controls(void)
|
|
{
|
|
int i;
|
|
if (shunted == 1)
|
|
return;
|
|
shunted = 1;
|
|
for (i = 0; i < NBUTTON; i++)
|
|
EnableWindow(button[i], FALSE);
|
|
EnableWindow(input_window, FALSE);
|
|
}
|
|
|
|
static void
|
|
activate_controls(void)
|
|
{
|
|
int i;
|
|
if (shunted == 0)
|
|
return;
|
|
shunted = 0;
|
|
for (i = 0; i < NBUTTON; i++)
|
|
EnableWindow(button[i], TRUE);
|
|
EnableWindow(input_window, TRUE);
|
|
SetFocus(input_window);
|
|
}
|
|
|
|
static void
|
|
do_enter(void)
|
|
{
|
|
if (running || edit_mode)
|
|
return;
|
|
if (inp)
|
|
free(inp);
|
|
inp = get_curr_cmd();
|
|
update_cmd_history(inp); // reset history pointer no matter what
|
|
if (*inp == 0)
|
|
return;
|
|
echo_input(inp);
|
|
update_curr_cmd("");
|
|
create_task();
|
|
}
|
|
|
|
static void
|
|
do_button(char *s)
|
|
{
|
|
char *tmp;
|
|
if (edit_mode == 0)
|
|
SetFocus(input_window);
|
|
if (running || edit_mode)
|
|
return;
|
|
if (inp)
|
|
free(inp);
|
|
inp = get_curr_cmd();
|
|
update_cmd_history(inp); // reset history pointer no matter what
|
|
if (*inp == 0) {
|
|
free(inp);
|
|
inp = (char *) malloc(strlen(s) + 7);
|
|
strcpy(inp, s);
|
|
} else {
|
|
tmp = (char *) malloc(strlen(s) + strlen(inp) + 3);
|
|
if (strcmp(s, "derivative") == 0)
|
|
strcpy(tmp, "d");
|
|
else
|
|
strcpy(tmp, s);
|
|
strcat(tmp, "(");
|
|
strcat(tmp, inp);
|
|
strcat(tmp, ")");
|
|
free(inp);
|
|
inp = tmp;
|
|
}
|
|
update_cmd_history(inp);
|
|
echo_input(inp);
|
|
update_curr_cmd("");
|
|
create_task();
|
|
}
|
|
|
|
static void
|
|
run_script(void)
|
|
{
|
|
int len;
|
|
if (edit_mode == 0)
|
|
SetFocus(input_window); // move focus from run button
|
|
if (running)
|
|
return;
|
|
if (inp)
|
|
free(inp);
|
|
len = GetWindowTextLength(edit_window);
|
|
inp = (char *) malloc(len + 1);
|
|
GetWindowText(edit_window, inp, len + 1);
|
|
goto_calc_mode();
|
|
deactivate_controls();
|
|
clear();
|
|
update_display();
|
|
create_task();
|
|
update_curr_cmd("Working...");
|
|
}
|
|
|
|
static void
|
|
copy_all(void)
|
|
{
|
|
HDC tmp;
|
|
RECT r;
|
|
HBITMAP bitmap;
|
|
if (total_h == 0)
|
|
return;
|
|
tmp = GetDC(main_window);
|
|
draw_hdc = CreateCompatibleDC(tmp);
|
|
r.left = 0;
|
|
r.top = 0;
|
|
r.right = display_width;
|
|
r.bottom = total_h - display_y;
|
|
if (r.bottom > display_height)
|
|
r.bottom = display_height;
|
|
bitmap = CreateCompatibleBitmap(tmp, r.right, r.bottom);
|
|
SelectObject(draw_hdc, bitmap);
|
|
FillRect(draw_hdc, &r, (HBRUSH) GetStockObject(WHITE_BRUSH));
|
|
SetBkMode(draw_hdc, TRANSPARENT);
|
|
draw_display();
|
|
OpenClipboard(main_window);
|
|
EmptyClipboard();
|
|
SetClipboardData(CF_BITMAP, bitmap);
|
|
CloseClipboard();
|
|
DeleteObject(bitmap);
|
|
DeleteDC(draw_hdc);
|
|
DeleteDC(tmp);
|
|
}
|
|
|
|
static void
|
|
do_special(char *s)
|
|
{
|
|
if (inp)
|
|
free(inp);
|
|
inp = strdup(s);
|
|
update_cmd_history(inp);
|
|
echo_input(inp);
|
|
update_curr_cmd("");
|
|
run(inp);
|
|
}
|
|
|
|
static void
|
|
do_help(char **s, int n)
|
|
{
|
|
int i;
|
|
if (running)
|
|
return;
|
|
goto_calc_mode();
|
|
run_hdc = GetDC(main_window);
|
|
do_special("clear");
|
|
for (i = 0; i < n; i++)
|
|
do_special(s[i]);
|
|
ReleaseDC(main_window, run_hdc);
|
|
update_display();
|
|
}
|