forked from Miroirs/x49gp
c61f11cff2
Misc changes, mostly fixes: - fix ./newconfig systems other than OSX (broke inc8b823f
) - fix palette usage in 2-bit color mode (was broken ever since grayscale was implemented in18e1003
and its improperly attributed copyf7913eb
) - fix continuing from breakpoints in the debugger (never worked, was exposed when the debugger was enabled in9c1f2ed
) - restore the printf statements commented out in9c1f2ed
and hide them with #ifdefs instead - close the server socket after accepting a debugger connection to allow another simultaneous debug session to be started using the same TCP port - use the symbolic constant DEFAULT_GDBSTUB_PORT (already defined in gdb_stub.h as 1234) when starting the gdb server in main.c in place of the raw number 1234 - change Makefile to read the name of the firmware file from the file update.scp instead of hardcoding it; this allows users to switch to another firmware by simply pasting it along with its accompanying update.scp into the x49gp directory - Enhance port G (keyboard) handling to remember the value of output bits across periods with these bits configured as input This fixes interaction with HPGCC3 keyboard routines, and it also fixes keys with eint==7 (assuming the stock firmware is in use) needing a double-tap to work unless pressed very shortly after another keypress (the latter broke inb5f93ed
) - Get rid of the deprecated function warning by switching from gdk_pixbuf_new_from_inline to gdk_pixbuf_new_from_data (based on code by chwdt) - Delete remaining now-redundant CVS files - Don't release all buttons anymore if there are still physical keys and/or the left mouse button are holding some down On the other hand, forcibly release all buttons when losing focus to avoid getting stuck in a state with buttons down when they are not held down by anything; this would happen due to missed events while not in focus - Add a context menu to the screen, containing only "Reset" and "Quit" items for now - Ensure that the files backing flash, sram, and s3c2410-sram exist and have the correct size when opening them Note that if the flash file does not exist, this will not fill it with the code that's supposed to be in there, obviously causing the calculator to crash. That's an improvement for later. - Allow the config system to fill not only numbers, but also strings (including filenames) with default values basename is excluded, but it's planned to be dropped entirely. - Add an "install" target to the Makefile - Implement a more generic command-line parser for substantially improved flexibility - Also adds a proper help option, though the manual referenced in the corresponding output (a manpage, hopefully) does not exist yet. - Drop the "basename" config property in favor of interpreting relative paths in the config as relative to the config file's location - Retire the "image" config property in favor of simply loading the image from next to the binary or from the install directory - Split the UI name property into name (affecting only the window title) and type (affecting the UI image and in the future also the default bootcode) properties - Change the default calculator type to the 50g everywhere, which probably matches today's user expectations better than the 49g+. - Create a flash file from the calculator model's appropriate boot file if it does not exist, relying on the bootcode to detect the absence of a firmware The bootcode will complain about the missing firmware and enter update mode, so the user needs to supply their favorite firmware version and point the bootcode's updater to it. The easiest way is probably pointing the emulated SD card at a directory containing the firmware and its accompanying update.scp file, and then starting the SD-based update. - Add SD mount / unmount options to the right-click / menu-key popup menu - Remove most of the old script-based config-generating system since the binary now has these capabilities as well - Add an applications menu item for installing - Keep some debug output on stderr and a huge vvfat.log file from showing up when not debugging x49gp itself - Allow (re-)connecting a debugger to a running session This is done through the right-click / menu-key popup menu. To avoid confusion due to the accidental clicks leading to an unresponsive interface (caused by waiting for the debugger to connect), this option is hidden unless option -d or its new companion -D (same as -d, but does not start the debug interface right away) is present. - Improved support for hardware keyboards - Update README.md, add manpage, rename other README files to TODO to reflect their contents
2737 lines
70 KiB
C
2737 lines
70 KiB
C
/* $Id: ui.c,v 1.34 2008/12/11 12:18:17 ecd Exp $
|
|
*/
|
|
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
#include <fcntl.h>
|
|
#include <signal.h>
|
|
#include <sys/times.h>
|
|
#include <math.h>
|
|
#include <errno.h>
|
|
#include <arpa/inet.h> /* For ntohl() */
|
|
|
|
#include <gtk/gtk.h>
|
|
#include <glib.h>
|
|
#include <cairo.h>
|
|
|
|
#include <x49gp.h>
|
|
#include <x49gp_ui.h>
|
|
#include <s3c2410.h>
|
|
#include <bitmaps.h>
|
|
#include <bitmap_font.h>
|
|
#include <symbol.h>
|
|
#include <glyphname.h>
|
|
|
|
#include "gdbstub.h"
|
|
|
|
#include <gdk/gdkkeysyms.h>
|
|
|
|
#if defined(__linux__)
|
|
#define X49GP_UI_NORMAL_FONT "urw gothic l"
|
|
#else
|
|
#define X49GP_UI_NORMAL_FONT "Century Gothic"
|
|
#endif
|
|
|
|
|
|
static const x49gp_ui_key_t x49gp_ui_keys[] =
|
|
{
|
|
{
|
|
"F1", "A", "Y=", NULL, NULL,
|
|
UI_COLOR_BLACK, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_TINY, 12.0, UI_LAYOUT_LEFT,
|
|
0, 0, 36, 22, 5, 1, (1 << 5), (1 << 1), 1
|
|
},
|
|
{
|
|
"F2", "B", "WIN", NULL, NULL,
|
|
UI_COLOR_BLACK, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_TINY, 12.0, UI_LAYOUT_LEFT,
|
|
50, 0, 36, 22, 5, 2, (1 << 5), (1 << 2), 2
|
|
},
|
|
{
|
|
"F3", "C", "GRAPH", NULL, NULL,
|
|
UI_COLOR_BLACK, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_TINY, 12.0, UI_LAYOUT_LEFT,
|
|
99, 0, 36, 22, 5, 3, (1 << 5), (1 << 3), 3
|
|
},
|
|
{
|
|
"F4", "D", "2D/3D", NULL, NULL,
|
|
UI_COLOR_BLACK, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_TINY, 12.0, UI_LAYOUT_LEFT,
|
|
149, 0, 36, 22, 5, 4, (1 << 5), (1 << 4), 4
|
|
},
|
|
{
|
|
"F5", "E", "TBLSET", NULL, NULL,
|
|
UI_COLOR_BLACK, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_TINY, 12.0, UI_LAYOUT_LEFT,
|
|
198, 0, 36, 22, 5, 5, (1 << 5), (1 << 5), 5
|
|
},
|
|
{
|
|
"F6", "F", "TABLE", NULL, NULL,
|
|
UI_COLOR_BLACK, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_TINY, 12.0, UI_LAYOUT_LEFT,
|
|
247, 0, 36, 22, 5, 6, (1 << 5), (1 << 6), 6
|
|
},
|
|
{
|
|
"APPS", "G", "FILES", "BEGIN", NULL,
|
|
UI_COLOR_WHITE, 10.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_SMALL, 10.0, UI_LAYOUT_BELOW,
|
|
0, 44, 36, 28, 5, 7, (1 << 5), (1 << 7), 7
|
|
},
|
|
{
|
|
"MODE", "H", "CUSTOM", "END", NULL,
|
|
UI_COLOR_WHITE, 10.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_SMALL, 10.0, UI_LAYOUT_BELOW,
|
|
50, 44, 36, 28, 6, 5, (1 << 6), (1 << 5), 5
|
|
},
|
|
{
|
|
"TOOL", "I", "i", "I", NULL,
|
|
UI_COLOR_WHITE, 10.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_SMALL, 10.0, UI_LAYOUT_BELOW,
|
|
99, 44, 36, 28, 6, 6, (1 << 6), (1 << 6), 6
|
|
},
|
|
{
|
|
"V\\kern-1 AR", "J", "UPDIR", "COPY", NULL,
|
|
UI_COLOR_WHITE, 10.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_SMALL, 10.0, UI_LAYOUT_BELOW,
|
|
0, 92, 36, 28, 6, 7, (1 << 6), (1 << 7), 7
|
|
},
|
|
{
|
|
"STO \\triangleright", "K", "RCL", "CUT", NULL,
|
|
UI_COLOR_WHITE, 10.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_SMALL, 10.0, UI_LAYOUT_BELOW,
|
|
50, 92, 36, 28, 7, 1, (1 << 7), (1 << 1), 1
|
|
},
|
|
{
|
|
"NXT", "L", "PREV", "PASTE", NULL,
|
|
UI_COLOR_WHITE, 10.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_SMALL, 10.0, UI_LAYOUT_BELOW,
|
|
99, 92, 36, 28, 7, 2, (1 << 7), (1 << 2), 2
|
|
},
|
|
{
|
|
NULL, NULL, NULL, NULL, NULL,
|
|
UI_COLOR_SILVER, 0.0, 0,
|
|
UI_SHAPE_BUTTON_ROUND, 0.0, 0,
|
|
200, 38, 33, 33, 6, 1, (1 << 6), (1 << 1), 1
|
|
},
|
|
{
|
|
NULL, NULL, NULL, NULL, NULL,
|
|
UI_COLOR_SILVER, 0.0, 0,
|
|
UI_SHAPE_BUTTON_ROUND, 0.0, 0,
|
|
164, 66, 33, 33, 6, 2, (1 << 6), (1 << 2), 2
|
|
},
|
|
{
|
|
NULL, NULL, NULL, NULL, NULL,
|
|
UI_COLOR_SILVER, 0.0, 0,
|
|
UI_SHAPE_BUTTON_ROUND, 0.0, 0,
|
|
200, 94, 33, 33, 6, 3, (1 << 6), (1 << 3), 3
|
|
},
|
|
{
|
|
NULL, NULL, NULL, NULL, NULL,
|
|
UI_COLOR_SILVER, 0.0, 0,
|
|
UI_SHAPE_BUTTON_ROUND, 0.0, 0,
|
|
236, 66, 33, 33, 6, 4, (1 << 6), (1 << 4), 4
|
|
},
|
|
{
|
|
"HIST", "M", "CMD", "UNDO", NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
0, 141, 46, 28, 4, 1, (1 << 4), (1 << 1), 1
|
|
},
|
|
{
|
|
"EV\\kern-1 AL", "N", "PRG", "CHARS", NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
59, 141, 46, 28, 3, 1, (1 << 3), (1 << 1), 1
|
|
},
|
|
{
|
|
"\\tick", "O", "MTRW", "EQW", NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
119, 141, 46, 28, 2, 1, (1 << 2), (1 << 1), 1
|
|
},
|
|
{
|
|
"S\\kern-1 Y\\kern-1 M\\kern-1 B", "P", "MTH", "CAT", NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
179, 141, 46, 28, 1, 1, (1 << 1), (1 << 1), 1
|
|
},
|
|
{
|
|
"\\arrowleftdblfull", NULL, "DEL", "CLEAR", NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 0.0, 0,
|
|
238, 141, 46, 28, 0, 1, (1 << 0), (1 << 1), 1
|
|
},
|
|
{
|
|
"Y\\super x\\/super", "Q", "\\math_e\\xsuperior", "LN", NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
0, 183, 46, 28, 4, 2, (1 << 4), (1 << 2), 2
|
|
},
|
|
{
|
|
"\\radical\\overscore\\kern-7 X", "R",
|
|
"\\math_x\\twosuperior",
|
|
"\\xsuperior\\kern-4\\math_radical\\overscore\\kern-5\\math_y",
|
|
NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
59, 183, 46, 28, 3, 2, (1 << 3), (1 << 2), 2
|
|
},
|
|
{
|
|
"SIN", "S", "ASIN", "\\math_summation", NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
119, 183, 46, 28, 2, 2, (1 << 2), (1 << 2), 2
|
|
},
|
|
{
|
|
"COS", "T", "ACOS", "\\math_partialdiff", NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
179, 183, 46, 28, 1, 2, (1 << 1), (1 << 2), 2
|
|
},
|
|
{
|
|
"TAN", "U", "ATAN", "\\math_integral", NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
238, 183, 46, 28, 0, 2, (1 << 0), (1 << 2), 2
|
|
},
|
|
{
|
|
"EEX", "V", "10\\xsuperior", "LOG", NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
0, 225, 46, 28, 4, 3, (1 << 4), (1 << 3), 3
|
|
},
|
|
{
|
|
"+\\divisionslash\\minus", "W",
|
|
"\\math_notequal",
|
|
"\\math_equal",
|
|
NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
59, 225, 46, 28, 3, 3, (1 << 3), (1 << 3), 3
|
|
},
|
|
{
|
|
"X", "X",
|
|
"\\math_lessequal",
|
|
"\\math_less",
|
|
NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
119, 225, 46, 28, 2, 3, (1 << 2), (1 << 3), 3
|
|
},
|
|
{
|
|
"1/X", "Y",
|
|
"\\math_greaterequal",
|
|
"\\math_greater",
|
|
NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
179, 225, 46, 28, 1, 3, (1 << 1), (1 << 3), 3
|
|
},
|
|
{
|
|
"\\divide", "Z", "ABS", "ARG", NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT_NO_SPACE,
|
|
238, 225, 46, 28, 0, 3, (1 << 0), (1 << 3), 3
|
|
},
|
|
{
|
|
"ALPHA", NULL, "USER", "ENTRY", NULL,
|
|
UI_COLOR_BLACK, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
0, 267, 46, 32, 0, 0, 0, 0, 4
|
|
},
|
|
{
|
|
"7", NULL, "S.SLV", "NUM.SLV", NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
59, 267, 46, 32, 3, 4, (1 << 3), (1 << 4), 4
|
|
},
|
|
{
|
|
"8", NULL, "EXP&LN", "TRIG", NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
119, 267, 46, 32, 2, 4, (1 << 2), (1 << 4), 4
|
|
},
|
|
{
|
|
"9", NULL, "FINANCE", "TIME", NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
179, 267, 46, 32, 1, 4, (1 << 1), (1 << 4), 4
|
|
},
|
|
{
|
|
"\\multiply", NULL, "[ ]", "\" \"", NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
238, 267, 46, 32, 0, 4, (1 << 0), (1 << 4), 4
|
|
},
|
|
{
|
|
"\\uparrowleft", NULL, NULL, NULL, NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
0, 313, 46, 32, 0, 0, 0, 0, 5
|
|
},
|
|
{
|
|
"4", NULL, "CALC", "ALG", NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
59, 313, 46, 32, 3, 5, (1 << 3), (1 << 5), 5
|
|
},
|
|
{
|
|
"5", NULL, "MATRICES", "STAT", NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
119, 313, 46, 32, 2, 5, (1 << 2), (1 << 5), 5
|
|
},
|
|
{
|
|
"6", NULL, "CONVERT", "UNITS", NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
179, 313, 46, 32, 1, 5, (1 << 1), (1 << 5), 5
|
|
},
|
|
{
|
|
"\\minus", NULL, "( )", "_", NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
238, 313, 46, 32, 0, 5, (1 << 0), (1 << 5), 5
|
|
},
|
|
{
|
|
"\\uparrowright", NULL, NULL, NULL, NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
0, 359, 46, 32, 0, 0, 0, 0, 6
|
|
},
|
|
{
|
|
"1", NULL, "ARITH", "CMPLX", NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
59, 359, 46, 32, 3, 6, (1 << 3), (1 << 6), 6
|
|
},
|
|
{
|
|
"2", NULL, "DEF", "LIB", NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
119, 359, 46, 32, 2, 6, (1 << 2), (1 << 6), 6
|
|
},
|
|
{
|
|
"3", NULL, "\\math_numbersign", "BASE", NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
179, 359, 46, 32, 1, 6, (1 << 1), (1 << 6), 6
|
|
},
|
|
{
|
|
"+", NULL,
|
|
"{ }",
|
|
"\\guillemotleft\\ \\guillemotright",
|
|
NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
238, 359, 46, 32, 0, 6, (1 << 0), (1 << 6), 6
|
|
},
|
|
{
|
|
"ON", NULL, "CONT", "OFF", "CANCEL",
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
0, 405, 46, 32, 0, 0, 0, 0, 0
|
|
},
|
|
{
|
|
"0", NULL,
|
|
"\\math_infinity",
|
|
"\\math_arrowright",
|
|
NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
59, 405, 46, 32, 3, 7, (1 << 3), (1 << 7), 7
|
|
},
|
|
{
|
|
"\\bullet", NULL,
|
|
": :",
|
|
"\\math_downarrowleft",
|
|
NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
119, 405, 46, 32, 2, 7, (1 << 2), (1 << 7), 7
|
|
},
|
|
{
|
|
"SPC", NULL,
|
|
"\\math_pi",
|
|
"\\large_comma",
|
|
NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
179, 405, 46, 32, 1, 7, (1 << 1), (1 << 7), 7
|
|
},
|
|
{
|
|
"ENTER", NULL, "ANS", "\\arrowright NUM", NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
238, 405, 46, 32, 0, 7, (1 << 0), (1 << 7), 7
|
|
},
|
|
};
|
|
#define X49GP_UI_NR_KEYS (sizeof(x49gp_ui_keys) / sizeof(x49gp_ui_keys[0]))
|
|
|
|
static const x49gp_ui_key_t x50g_ui_keys[] =
|
|
{
|
|
{
|
|
"F1", "A", "Y=", NULL, NULL,
|
|
UI_COLOR_BLACK, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_TINY, 12.0, UI_LAYOUT_LEFT,
|
|
0, 0, 36, 22, 5, 1, (1 << 5), (1 << 1), 1
|
|
},
|
|
{
|
|
"F2", "B", "WIN", NULL, NULL,
|
|
UI_COLOR_BLACK, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_TINY, 12.0, UI_LAYOUT_LEFT,
|
|
50, 0, 36, 22, 5, 2, (1 << 5), (1 << 2), 2
|
|
},
|
|
{
|
|
"F3", "C", "GRAPH", NULL, NULL,
|
|
UI_COLOR_BLACK, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_TINY, 12.0, UI_LAYOUT_LEFT,
|
|
99, 0, 36, 22, 5, 3, (1 << 5), (1 << 3), 3
|
|
},
|
|
{
|
|
"F4", "D", "2D/3D", NULL, NULL,
|
|
UI_COLOR_BLACK, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_TINY, 12.0, UI_LAYOUT_LEFT,
|
|
149, 0, 36, 22, 5, 4, (1 << 5), (1 << 4), 4
|
|
},
|
|
{
|
|
"F5", "E", "TBLSET", NULL, NULL,
|
|
UI_COLOR_BLACK, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_TINY, 12.0, UI_LAYOUT_LEFT,
|
|
198, 0, 36, 22, 5, 5, (1 << 5), (1 << 5), 5
|
|
},
|
|
{
|
|
"F6", "F", "TABLE", NULL, NULL,
|
|
UI_COLOR_BLACK, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_TINY, 12.0, UI_LAYOUT_LEFT,
|
|
247, 0, 36, 22, 5, 6, (1 << 5), (1 << 6), 6
|
|
},
|
|
{
|
|
"APPS", "G", "FILES", "BEGIN", NULL,
|
|
UI_COLOR_WHITE, 10.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_SMALL, 10.0, UI_LAYOUT_BELOW,
|
|
0, 44, 36, 28, 5, 7, (1 << 5), (1 << 7), 7
|
|
},
|
|
{
|
|
"MODE", "H", "CUSTOM", "END", NULL,
|
|
UI_COLOR_WHITE, 10.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_SMALL, 10.0, UI_LAYOUT_BELOW,
|
|
50, 44, 36, 28, 6, 5, (1 << 6), (1 << 5), 5
|
|
},
|
|
{
|
|
"TOOL", "I", "i", "I", NULL,
|
|
UI_COLOR_WHITE, 10.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_SMALL, 10.0, UI_LAYOUT_BELOW,
|
|
99, 44, 36, 28, 6, 6, (1 << 6), (1 << 6), 6
|
|
},
|
|
{
|
|
"V\\kern-1 AR", "J", "UPDIR", "COPY", NULL,
|
|
UI_COLOR_WHITE, 10.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_SMALL, 10.0, UI_LAYOUT_BELOW,
|
|
0, 92, 36, 28, 6, 7, (1 << 6), (1 << 7), 7
|
|
},
|
|
{
|
|
"STO \\triangleright", "K", "RCL", "CUT", NULL,
|
|
UI_COLOR_WHITE, 10.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_SMALL, 10.0, UI_LAYOUT_BELOW,
|
|
50, 92, 36, 28, 7, 1, (1 << 7), (1 << 1), 1
|
|
},
|
|
{
|
|
"NXT", "L", "PREV", "PASTE", NULL,
|
|
UI_COLOR_WHITE, 10.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_SMALL, 10.0, UI_LAYOUT_BELOW,
|
|
99, 92, 36, 28, 7, 2, (1 << 7), (1 << 2), 2
|
|
},
|
|
{
|
|
NULL, NULL, NULL, NULL, NULL,
|
|
UI_COLOR_SILVER, 0.0, 0,
|
|
UI_SHAPE_BUTTON_ROUND, 0.0, 0,
|
|
200, 38, 33, 33, 6, 1, (1 << 6), (1 << 1), 1
|
|
},
|
|
{
|
|
NULL, NULL, NULL, NULL, NULL,
|
|
UI_COLOR_SILVER, 0.0, 0,
|
|
UI_SHAPE_BUTTON_ROUND, 0.0, 0,
|
|
164, 66, 33, 33, 6, 2, (1 << 6), (1 << 2), 2
|
|
},
|
|
{
|
|
NULL, NULL, NULL, NULL, NULL,
|
|
UI_COLOR_SILVER, 0.0, 0,
|
|
UI_SHAPE_BUTTON_ROUND, 0.0, 0,
|
|
200, 94, 33, 33, 6, 3, (1 << 6), (1 << 3), 3
|
|
},
|
|
{
|
|
NULL, NULL, NULL, NULL, NULL,
|
|
UI_COLOR_SILVER, 0.0, 0,
|
|
UI_SHAPE_BUTTON_ROUND, 0.0, 0,
|
|
236, 66, 33, 33, 6, 4, (1 << 6), (1 << 4), 4
|
|
},
|
|
{
|
|
"HIST", "M", "CMD", "UNDO", NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
0, 141, 46, 28, 4, 1, (1 << 4), (1 << 1), 1
|
|
},
|
|
{
|
|
"EV\\kern-1 AL", "N", "PRG", "CHARS", NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
59, 141, 46, 28, 3, 1, (1 << 3), (1 << 1), 1
|
|
},
|
|
{
|
|
"\\tick", "O", "MTRW", "EQW", NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
119, 141, 46, 28, 2, 1, (1 << 2), (1 << 1), 1
|
|
},
|
|
{
|
|
"S\\kern-1 Y\\kern-1 M\\kern-1 B", "P", "MTH", "CAT", NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
179, 141, 46, 28, 1, 1, (1 << 1), (1 << 1), 1
|
|
},
|
|
{
|
|
"\\arrowleftdblfull", NULL, "DEL", "CLEAR", NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 0.0, 0,
|
|
238, 141, 46, 28, 0, 1, (1 << 0), (1 << 1), 1
|
|
},
|
|
{
|
|
"Y\\super x\\/super", "Q", "\\math_e\\xsuperior", "LN", NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
0, 183, 46, 28, 4, 2, (1 << 4), (1 << 2), 2
|
|
},
|
|
{
|
|
"\\radical\\overscore\\kern-7 X", "R",
|
|
"\\math_x\\twosuperior",
|
|
"\\xsuperior\\kern-4\\math_radical\\overscore\\kern-5\\math_y",
|
|
NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
59, 183, 46, 28, 3, 2, (1 << 3), (1 << 2), 2
|
|
},
|
|
{
|
|
"SIN", "S", "ASIN", "\\math_summation", NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
119, 183, 46, 28, 2, 2, (1 << 2), (1 << 2), 2
|
|
},
|
|
{
|
|
"COS", "T", "ACOS", "\\math_partialdiff", NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
179, 183, 46, 28, 1, 2, (1 << 1), (1 << 2), 2
|
|
},
|
|
{
|
|
"TAN", "U", "ATAN", "\\math_integral", NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
238, 183, 46, 28, 0, 2, (1 << 0), (1 << 2), 2
|
|
},
|
|
{
|
|
"EEX", "V", "10\\xsuperior", "LOG", NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
0, 225, 46, 28, 4, 3, (1 << 4), (1 << 3), 3
|
|
},
|
|
{
|
|
"+\\divisionslash\\minus", "W",
|
|
"\\math_notequal",
|
|
"\\math_equal",
|
|
NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
59, 225, 46, 28, 3, 3, (1 << 3), (1 << 3), 3
|
|
},
|
|
{
|
|
"X", "X",
|
|
"\\math_lessequal",
|
|
"\\math_less",
|
|
NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
119, 225, 46, 28, 2, 3, (1 << 2), (1 << 3), 3
|
|
},
|
|
{
|
|
"1/X", "Y",
|
|
"\\math_greaterequal",
|
|
"\\math_greater",
|
|
NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT,
|
|
179, 225, 46, 28, 1, 3, (1 << 1), (1 << 3), 3
|
|
},
|
|
{
|
|
"\\divide", "Z", "ABS", "ARG", NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_NORMAL, 12.0, UI_LAYOUT_LEFT_NO_SPACE,
|
|
238, 225, 46, 28, 0, 3, (1 << 0), (1 << 3), 3
|
|
},
|
|
{
|
|
"ALPHA", NULL, "USER", "ENTRY", NULL,
|
|
UI_COLOR_BLACK, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
0, 267, 46, 32, 0, 0, 0, 0, 4
|
|
},
|
|
{
|
|
"7", NULL, "S.SLV", "NUM.SLV", NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
59, 267, 46, 32, 3, 4, (1 << 3), (1 << 4), 4
|
|
},
|
|
{
|
|
"8", NULL, "EXP&LN", "TRIG", NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
119, 267, 46, 32, 2, 4, (1 << 2), (1 << 4), 4
|
|
},
|
|
{
|
|
"9", NULL, "FINANCE", "TIME", NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
179, 267, 46, 32, 1, 4, (1 << 1), (1 << 4), 4
|
|
},
|
|
{
|
|
"\\multiply", NULL, "[ ]", "\" \"", NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
238, 267, 46, 32, 0, 4, (1 << 0), (1 << 4), 4
|
|
},
|
|
{
|
|
"\\uparrowleft", NULL, NULL, NULL, NULL,
|
|
UI_COLOR_BLACK, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
0, 313, 46, 32, 0, 0, 0, 0, 5
|
|
},
|
|
{
|
|
"4", NULL, "CALC", "ALG", NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
59, 313, 46, 32, 3, 5, (1 << 3), (1 << 5), 5
|
|
},
|
|
{
|
|
"5", NULL, "MATRICES", "STAT", NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
119, 313, 46, 32, 2, 5, (1 << 2), (1 << 5), 5
|
|
},
|
|
{
|
|
"6", NULL, "CONVERT", "UNITS", NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
179, 313, 46, 32, 1, 5, (1 << 1), (1 << 5), 5
|
|
},
|
|
{
|
|
"\\minus", NULL, "( )", "_", NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
238, 313, 46, 32, 0, 5, (1 << 0), (1 << 5), 5
|
|
},
|
|
{
|
|
"\\uparrowright", NULL, NULL, NULL, NULL,
|
|
UI_COLOR_BLACK, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
0, 359, 46, 32, 0, 0, 0, 0, 6
|
|
},
|
|
{
|
|
"1", NULL, "ARITH", "CMPLX", NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
59, 359, 46, 32, 3, 6, (1 << 3), (1 << 6), 6
|
|
},
|
|
{
|
|
"2", NULL, "DEF", "LIB", NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
119, 359, 46, 32, 2, 6, (1 << 2), (1 << 6), 6
|
|
},
|
|
{
|
|
"3", NULL, "\\math_numbersign", "BASE", NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
179, 359, 46, 32, 1, 6, (1 << 1), (1 << 6), 6
|
|
},
|
|
{
|
|
"+", NULL,
|
|
"{ }",
|
|
"\\guillemotleft\\ \\guillemotright",
|
|
NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
238, 359, 46, 32, 0, 6, (1 << 0), (1 << 6), 6
|
|
},
|
|
{
|
|
"ON", NULL, "CONT", "OFF", "CANCEL",
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
0, 405, 46, 32, 0, 0, 0, 0, 0
|
|
},
|
|
{
|
|
"0", NULL,
|
|
"\\math_infinity",
|
|
"\\math_arrowright",
|
|
NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
59, 405, 46, 32, 3, 7, (1 << 3), (1 << 7), 7
|
|
},
|
|
{
|
|
"\\bullet", NULL,
|
|
": :",
|
|
"\\math_downarrowleft",
|
|
NULL,
|
|
UI_COLOR_WHITE, 19.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
119, 405, 46, 32, 2, 7, (1 << 2), (1 << 7), 7
|
|
},
|
|
{
|
|
"SPC", NULL,
|
|
"\\math_pi",
|
|
"\\large_comma",
|
|
NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
179, 405, 46, 32, 1, 7, (1 << 1), (1 << 7), 7
|
|
},
|
|
{
|
|
"ENTER", NULL, "ANS", "\\arrowright NUM", NULL,
|
|
UI_COLOR_WHITE, 12.0, CAIRO_FONT_WEIGHT_BOLD,
|
|
UI_SHAPE_BUTTON_LARGE, 0.0, 0,
|
|
238, 405, 46, 32, 0, 7, (1 << 0), (1 << 7), 7
|
|
},
|
|
};
|
|
#define X50G_UI_NR_KEYS (sizeof(x50g_ui_keys) / sizeof(x50g_ui_keys[0]))
|
|
|
|
static void
|
|
x49gp_ui_color_init(GdkColor *color, u8 red, u8 green, u8 blue)
|
|
{
|
|
color->red = (red << 8) | red;
|
|
color->green = (green << 8) | green;
|
|
color->blue = (blue << 8) | blue;
|
|
}
|
|
|
|
static void
|
|
x49gp_ui_style_init(GtkStyle *style, GtkWidget *widget,
|
|
GdkColor *fg, GdkColor *bg)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 5; i++) {
|
|
style->fg[i] = *fg;
|
|
style->bg[i] = *bg;
|
|
|
|
style->text[i] = style->fg[i];
|
|
style->base[i] = style->bg[i];
|
|
}
|
|
|
|
style->xthickness = 0;
|
|
style->ythickness = 0;
|
|
}
|
|
|
|
static const uint32_t PIXBUF_MAGIC = 0x47646b50;
|
|
|
|
typedef struct {
|
|
uint32_t magic;
|
|
uint32_t length;
|
|
uint32_t pixdata_type;
|
|
uint32_t rowstride;
|
|
uint32_t width;
|
|
uint32_t height;
|
|
} pixbuf_inline_data_t;
|
|
|
|
static GdkPixbuf *
|
|
x49gp_pixbuf_new_from_inline(gint data_length, const guint8 *data)
|
|
{
|
|
const pixbuf_inline_data_t *pbd = (const pixbuf_inline_data_t *) data;
|
|
uint32_t magic, rowstride, width, height, length;
|
|
const guint8 *pixdata;
|
|
|
|
magic = ntohl(pbd->magic);
|
|
if (magic != PIXBUF_MAGIC) {
|
|
return NULL;
|
|
}
|
|
|
|
length = ntohl(pbd->length);
|
|
/* The data comes from a C string, which contains a trailing \0. */
|
|
/* This will be counted by sizeof(), but the embedded header */
|
|
/* specifies the true size. Compensate by adding 1 to it. */
|
|
if (length + 1 != data_length) {
|
|
return NULL;
|
|
}
|
|
|
|
width = ntohl(pbd->width);
|
|
height = ntohl(pbd->height);
|
|
rowstride = ntohl(pbd->rowstride);
|
|
|
|
pixdata = (void *) (pbd + 1);
|
|
|
|
return gdk_pixbuf_new_from_data(pixdata, GDK_COLORSPACE_RGB, TRUE, 8,
|
|
width, height, rowstride, NULL, NULL);
|
|
}
|
|
|
|
static int
|
|
x49gp_ui_button_pixmaps_init(x49gp_t *x49gp, x49gp_ui_button_t *button,
|
|
x49gp_ui_color_t color)
|
|
{
|
|
x49gp_ui_t *ui = x49gp->ui;
|
|
GdkPixbuf *src, *dst;
|
|
GtkStyle *style;
|
|
int i;
|
|
|
|
style = gtk_style_new();
|
|
x49gp_ui_style_init(style, button->button,
|
|
&ui->colors[button->key->color],
|
|
&ui->colors[UI_COLOR_BLACK]);
|
|
|
|
for (i = 0; i < 5; i++) {
|
|
style->bg_pixmap[i] = gdk_pixmap_new(ui->window->window,
|
|
button->key->width,
|
|
button->key->height, -1);
|
|
|
|
if (i == GTK_STATE_ACTIVE) {
|
|
if (color == UI_COLOR_SILVER) {
|
|
|
|
src = gdk_pixbuf_new_subpixbuf(ui->bg_pixbuf,
|
|
ui->kb_x_offset + button->key->x,
|
|
ui->kb_y_offset + button->key->y,
|
|
button->key->width,
|
|
button->key->height);
|
|
dst = gdk_pixbuf_copy(src);
|
|
g_object_unref(src);
|
|
|
|
src = x49gp_pixbuf_new_from_inline(sizeof(button_round),
|
|
button_round);
|
|
|
|
gdk_pixbuf_composite(src, dst,
|
|
0, 0,
|
|
button->key->width,
|
|
button->key->height,
|
|
0.0, 0.0, 1.0, 1.0,
|
|
GDK_INTERP_HYPER, 0xff);
|
|
|
|
g_object_unref(src);
|
|
src = dst;
|
|
} else {
|
|
src = gdk_pixbuf_new_subpixbuf(ui->bg_pixbuf,
|
|
ui->kb_x_offset + button->key->x,
|
|
ui->kb_y_offset + button->key->y + 1,
|
|
button->key->width,
|
|
button->key->height);
|
|
}
|
|
} else {
|
|
src = gdk_pixbuf_new_subpixbuf(ui->bg_pixbuf,
|
|
ui->kb_x_offset + button->key->x,
|
|
ui->kb_y_offset + button->key->y,
|
|
button->key->width,
|
|
button->key->height);
|
|
}
|
|
|
|
gdk_draw_pixbuf(style->bg_pixmap[i],
|
|
ui->window->style->black_gc,
|
|
src, 0, 0, 0, 0,
|
|
button->key->width, button->key->height,
|
|
GDK_RGB_DITHER_NORMAL, 0, 0);
|
|
|
|
g_object_unref(src);
|
|
}
|
|
|
|
gtk_widget_set_style(button->button, style);
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
x49gp_ui_symbol_path(cairo_t *cr, double size,
|
|
double xoffset, double yoffset,
|
|
const x49gp_symbol_t *symbol)
|
|
{
|
|
const symbol_path_t *path;
|
|
const cairo_path_data_t *data;
|
|
int i;
|
|
|
|
path = symbol->path;
|
|
if (NULL == path) {
|
|
return;
|
|
}
|
|
|
|
cairo_move_to(cr, xoffset, yoffset);
|
|
|
|
for (i = 0; i < path->num_data; i += path->data[i].header.length) {
|
|
data = &path->data[i];
|
|
|
|
switch (data->header.type) {
|
|
case CAIRO_PATH_MOVE_TO:
|
|
cairo_rel_move_to(cr, size * data[1].point.x,
|
|
-size * data[1].point.y);
|
|
break;
|
|
case CAIRO_PATH_LINE_TO:
|
|
cairo_rel_line_to(cr, size * data[1].point.x,
|
|
-size * data[1].point.y);
|
|
break;
|
|
case CAIRO_PATH_CURVE_TO:
|
|
cairo_rel_curve_to(cr, size * data[1].point.x,
|
|
-size * data[1].point.y,
|
|
size * data[2].point.x,
|
|
-size * data[2].point.y,
|
|
size * data[3].point.x,
|
|
-size * data[3].point.y);
|
|
break;
|
|
case CAIRO_PATH_CLOSE_PATH:
|
|
cairo_close_path(cr);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
x49gp_ui_draw_symbol(cairo_t *cr, GdkColor *color, double size,
|
|
double line_width, gboolean fill,
|
|
double xoffset, double yoffset,
|
|
const x49gp_symbol_t *symbol)
|
|
{
|
|
cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
|
|
cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER);
|
|
cairo_set_line_width(cr, line_width);
|
|
cairo_set_source_rgb(cr, ((double) color->red) / 65535.0,
|
|
((double) color->green) / 65535.0,
|
|
((double) color->blue) / 65535.0);
|
|
|
|
x49gp_ui_symbol_path(cr, size, xoffset, yoffset, symbol);
|
|
|
|
if (fill) {
|
|
cairo_fill(cr);
|
|
} else {
|
|
cairo_stroke(cr);
|
|
}
|
|
}
|
|
|
|
static int
|
|
x49gp_ui_lookup_glyph(const char *name, int namelen, gunichar *glyph)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < NR_GLYPHNAMES; i++) {
|
|
if ((strlen(x49gp_glyphs[i].name) == namelen) &&
|
|
!strncmp(x49gp_glyphs[i].name, name, namelen)) {
|
|
if (glyph)
|
|
*glyph = x49gp_glyphs[i].unichar;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
x49gp_text_strlen(const char *text)
|
|
{
|
|
const char *p, *q;
|
|
char c;
|
|
int namelen;
|
|
int n = 0;
|
|
|
|
p = text;
|
|
while ((c = *p++)) {
|
|
if (c != '\\') {
|
|
n++;
|
|
continue;
|
|
}
|
|
|
|
q = p;
|
|
while (*q) {
|
|
if ((*q == '\\') || (*q == ' '))
|
|
break;
|
|
q++;
|
|
}
|
|
if (q == p) {
|
|
n++;
|
|
p++;
|
|
continue;
|
|
}
|
|
namelen = q - p;
|
|
if (*q == ' ')
|
|
q++;
|
|
|
|
if (symbol_lookup_glyph_by_name(p, namelen, NULL)) {
|
|
p = q;
|
|
n++;
|
|
continue;
|
|
}
|
|
|
|
if (x49gp_ui_lookup_glyph(p, namelen, NULL)) {
|
|
p = q;
|
|
n++;
|
|
continue;
|
|
}
|
|
|
|
/*
|
|
* Insert symbol .notdef here...
|
|
*/
|
|
p = q;
|
|
n++;
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
static int
|
|
x49gp_text_to_ucs4(const char *text, gunichar **ucs4p)
|
|
{
|
|
const char *p, *q;
|
|
gunichar glyph;
|
|
gunichar *ucs4;
|
|
char c;
|
|
int namelen;
|
|
int i, n;
|
|
|
|
n = x49gp_text_strlen(text);
|
|
if (n <= 0)
|
|
return n;
|
|
|
|
ucs4 = malloc(n * sizeof(gunichar));
|
|
|
|
i = 0;
|
|
|
|
p = text;
|
|
while ((c = *p++)) {
|
|
if (i == n) {
|
|
free(ucs4);
|
|
return -1;
|
|
}
|
|
|
|
if (c != '\\') {
|
|
ucs4[i++] = c;
|
|
continue;
|
|
}
|
|
|
|
q = p;
|
|
while (*q) {
|
|
if ((*q == '\\') || (*q == ' '))
|
|
break;
|
|
q++;
|
|
}
|
|
if (q == p) {
|
|
ucs4[i++] = *p++;
|
|
continue;
|
|
}
|
|
namelen = q - p;
|
|
if (*q == ' ')
|
|
q++;
|
|
|
|
if (symbol_lookup_glyph_by_name(p, namelen, &glyph)) {
|
|
ucs4[i++] = glyph;
|
|
p = q;
|
|
continue;
|
|
}
|
|
|
|
if (x49gp_ui_lookup_glyph(p, namelen, &glyph)) {
|
|
ucs4[i++] = glyph;
|
|
p = q;
|
|
continue;
|
|
}
|
|
|
|
/*
|
|
* Insert symbol .notdef here...
|
|
*/
|
|
ucs4[i++] = 0xe000;
|
|
p = q;
|
|
}
|
|
|
|
*ucs4p = ucs4;
|
|
return n;
|
|
}
|
|
|
|
static void
|
|
x49gp_ui_vtext_path(cairo_t *cr, const char *family, double size,
|
|
double x, double y, int n, va_list ap)
|
|
{
|
|
cairo_text_extents_t extents;
|
|
cairo_font_weight_t weight;
|
|
cairo_font_slant_t slant;
|
|
const x49gp_symbol_t *symbol;
|
|
const char *text;
|
|
gunichar *ucs4;
|
|
char out[8];
|
|
int bytes;
|
|
int i, j, len;
|
|
|
|
for (i = 0; i < n; i++) {
|
|
slant = va_arg(ap, cairo_font_slant_t);
|
|
weight = va_arg(ap, cairo_font_weight_t);
|
|
text = va_arg(ap, const char *);
|
|
|
|
cairo_select_font_face(cr, family, slant, weight);
|
|
cairo_set_font_size(cr, size);
|
|
|
|
ucs4 = NULL;
|
|
len = x49gp_text_to_ucs4(text, &ucs4);
|
|
if (len <= 0) {
|
|
continue;
|
|
}
|
|
|
|
for (j = 0; j < len; j++) {
|
|
if (g_unichar_type(ucs4[j]) == G_UNICODE_PRIVATE_USE) {
|
|
/*
|
|
* Draw Symbol, Increment x...
|
|
*/
|
|
symbol = symbol_get_by_glyph(ucs4[j]);
|
|
if (NULL == symbol)
|
|
symbol = symbol_get_by_glyph(0xe000);
|
|
|
|
size *= symbol->prescale;
|
|
|
|
x49gp_ui_symbol_path(cr, size, x, y, symbol);
|
|
|
|
x += size * symbol->x_advance;
|
|
y -= size * symbol->y_advance;
|
|
|
|
size *= symbol->postscale;
|
|
|
|
if (symbol->prescale * symbol->postscale != 1.)
|
|
cairo_set_font_size(cr, size);
|
|
|
|
continue;
|
|
}
|
|
|
|
bytes = g_unichar_to_utf8(ucs4[j], out);
|
|
out[bytes] = '\0';
|
|
|
|
cairo_text_extents(cr, out, &extents);
|
|
|
|
cairo_move_to(cr, x, y);
|
|
|
|
cairo_text_path(cr, out);
|
|
|
|
x += extents.x_advance;
|
|
y += extents.y_advance;
|
|
}
|
|
|
|
free(ucs4);
|
|
}
|
|
}
|
|
|
|
static void
|
|
x49gp_ui_text_size(cairo_t *cr, const char *family, double size,
|
|
double *x_bearing, double *y_bearing,
|
|
double *width, double *height,
|
|
double *ascent, double *descent,
|
|
int n, ...)
|
|
{
|
|
va_list ap0, ap1;
|
|
cairo_font_extents_t font_extents;
|
|
cairo_font_weight_t weight;
|
|
cairo_font_slant_t slant;
|
|
double x1, y1, x2, y2, a, d;
|
|
const char *text;
|
|
int i;
|
|
|
|
if (n < 1)
|
|
return;
|
|
|
|
va_start(ap0, n);
|
|
va_copy(ap1, ap0);
|
|
|
|
x49gp_ui_vtext_path(cr, family, size, 0.0, 0.0, n, ap0);
|
|
|
|
va_end(ap0);
|
|
|
|
cairo_fill_extents(cr, &x1, &y1, &x2, &y2);
|
|
|
|
if (y2 < 0.0)
|
|
y2 = 0.0;
|
|
|
|
a = 0.0;
|
|
d = 0.0;
|
|
|
|
for (i = 0; i < n; i++) {
|
|
slant = va_arg(ap1, cairo_font_slant_t);
|
|
weight = va_arg(ap1, cairo_font_weight_t);
|
|
text = va_arg(ap1, const char *);
|
|
(void) text;
|
|
|
|
cairo_select_font_face(cr, family, slant, weight);
|
|
cairo_set_font_size(cr, size);
|
|
|
|
cairo_font_extents(cr, &font_extents);
|
|
|
|
/*
|
|
* Cairo seems to return overall height in ascent,
|
|
* so fix this by calculating ascent = height - descent.
|
|
*/
|
|
if (font_extents.ascent - font_extents.descent > a)
|
|
a = font_extents.ascent - font_extents.descent;
|
|
if (font_extents.descent > -d)
|
|
d = -font_extents.descent;
|
|
}
|
|
|
|
*x_bearing = x1;
|
|
*y_bearing = y2;
|
|
*width = x2 - x1;
|
|
*height = y2 - y1;
|
|
*ascent = a;
|
|
*descent = d;
|
|
|
|
va_end(ap1);
|
|
}
|
|
|
|
static void
|
|
x49gp_ui_draw_text(cairo_t *cr, GdkColor *color,
|
|
const char *family, double size, double line_width,
|
|
int xoffset, int yoffset, int n, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
if (n < 1)
|
|
return;
|
|
|
|
va_start(ap, n);
|
|
|
|
cairo_set_line_width(cr, line_width);
|
|
cairo_set_source_rgb(cr, ((double) color->red) / 65535.0,
|
|
((double) color->green) / 65535.0,
|
|
((double) color->blue) / 65535.0);
|
|
|
|
x49gp_ui_vtext_path(cr, family, size, xoffset, yoffset, n, ap);
|
|
|
|
if (line_width == 0.0)
|
|
cairo_fill(cr);
|
|
else
|
|
cairo_stroke(cr);
|
|
|
|
va_end(ap);
|
|
}
|
|
|
|
#if 0
|
|
static void
|
|
x49gp_ui_dump_path(cairo_t *cr, const char *family, int n, ...)
|
|
{
|
|
va_list ap;
|
|
const cairo_path_t *path;
|
|
const cairo_path_data_t *data;
|
|
int i;
|
|
|
|
if (n < 1)
|
|
return;
|
|
|
|
va_start(ap, n);
|
|
|
|
x49gp_ui_vtext_path(cr, family, 1000.0, 0.0, 0.0, n, ap);
|
|
|
|
path = cairo_copy_path(cr);
|
|
if (NULL == path) {
|
|
return;
|
|
}
|
|
cairo_new_path(cr);
|
|
|
|
for (i = 0; i < path->num_data; i += path->data[i].header.length) {
|
|
data = &path->data[i];
|
|
|
|
switch (data->header.type) {
|
|
case CAIRO_PATH_MOVE_TO:
|
|
printf("path: move to %4.0f %4.0f\n",
|
|
data[1].point.x, -data[1].point.y);
|
|
break;
|
|
case CAIRO_PATH_LINE_TO:
|
|
printf("path: line to %4.0f %4.0f\n",
|
|
data[1].point.x, -data[1].point.y);
|
|
break;
|
|
case CAIRO_PATH_CURVE_TO:
|
|
printf("path: curve to %4.0f %4.0f\n"
|
|
" %4.0f %4.0f\n"
|
|
" %4.0f %4.0f\n",
|
|
data[1].point.x, -data[1].point.y,
|
|
data[2].point.x, -data[2].point.y,
|
|
data[3].point.x, -data[3].point.y);
|
|
break;
|
|
case CAIRO_PATH_CLOSE_PATH:
|
|
printf("path: close path\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
va_end(ap);
|
|
}
|
|
#endif
|
|
|
|
static unsigned char
|
|
bitmap_font_lookup_glyph(const bitmap_font_t *font,
|
|
const char *name, int namelen)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; font->glyphs[i].name; i++) {
|
|
if ((strlen(font->glyphs[i].name) == namelen) &&
|
|
!strncmp(font->glyphs[i].name, name, namelen)) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static unsigned char
|
|
bitmap_font_lookup_ascii(const bitmap_font_t *font, char c)
|
|
{
|
|
int namelen = 0;
|
|
char *name;
|
|
|
|
switch (c) {
|
|
case ' ': name = "space"; break;
|
|
case '!': name = "exclam"; break;
|
|
case '"': name = "quotedbl"; break;
|
|
case '#': name = "numbersign"; break;
|
|
case '$': name = "dollar"; break;
|
|
case '%': name = "percent"; break;
|
|
case '&': name = "ampersand"; break;
|
|
case '(': name = "parenleft"; break;
|
|
case ')': name = "parenright"; break;
|
|
case '*': name = "asterisk"; break;
|
|
case '+': name = "plus"; break;
|
|
case ',': name = "comma"; break;
|
|
case '-': name = "hyphen"; break;
|
|
case '.': name = "period"; break;
|
|
case '/': name = "slash"; break;
|
|
case '0': name = "zero"; break;
|
|
case '1': name = "one"; break;
|
|
case '2': name = "two"; break;
|
|
case '3': name = "three"; break;
|
|
case '4': name = "four"; break;
|
|
case '5': name = "five"; break;
|
|
case '6': name = "six"; break;
|
|
case '7': name = "seven"; break;
|
|
case '8': name = "eight"; break;
|
|
case '9': name = "nine"; break;
|
|
case ':': name = "colon"; break;
|
|
case ';': name = "semicolon"; break;
|
|
case '<': name = "less"; break;
|
|
case '=': name = "equal"; break;
|
|
case '>': name = "greater"; break;
|
|
case '?': name = "question"; break;
|
|
case '@': name = "at"; break;
|
|
case '[': name = "bracketleft"; break;
|
|
case '\\': name = "backslash"; break;
|
|
case ']': name = "bracketright"; break;
|
|
case '^': name = "asciicircum"; break;
|
|
case '_': name = "underscore"; break;
|
|
case '`': name = "quoteleft"; break;
|
|
case '{': name = "braceleft"; break;
|
|
case '|': name = "bar"; break;
|
|
case '}': name = "braceright"; break;
|
|
case '~': name = "asciitilde"; break;
|
|
default:
|
|
name = &c;
|
|
namelen = 1;
|
|
break;
|
|
}
|
|
|
|
if (0 == namelen)
|
|
namelen = strlen(name);
|
|
|
|
return bitmap_font_lookup_glyph(font, name, namelen);
|
|
}
|
|
|
|
static int
|
|
bitmap_font_strlen(const char *text)
|
|
{
|
|
const char *p, *q;
|
|
char c;
|
|
int n = 0;
|
|
|
|
p = text;
|
|
while ((c = *p++)) {
|
|
if (c != '\\') {
|
|
n++;
|
|
continue;
|
|
}
|
|
|
|
q = p;
|
|
while (*q) {
|
|
if ((*q == '\\') || (*q == ' '))
|
|
break;
|
|
q++;
|
|
}
|
|
if (q == p) {
|
|
n++;
|
|
p++;
|
|
continue;
|
|
}
|
|
if (*q == ' ')
|
|
q++;
|
|
|
|
n++;
|
|
p = q;
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
static int
|
|
bitmap_font_text_to_glyphs(const bitmap_font_t *font,
|
|
const char *text, unsigned char **glyphp)
|
|
{
|
|
unsigned char *glyphs;
|
|
const char *p, *q;
|
|
unsigned char c;
|
|
int namelen;
|
|
int i, n;
|
|
|
|
n = bitmap_font_strlen(text);
|
|
if (n <= 0)
|
|
return n;
|
|
|
|
glyphs = malloc(n);
|
|
|
|
i = 0;
|
|
|
|
p = text;
|
|
while ((c = *p++)) {
|
|
if (i == n) {
|
|
free(glyphs);
|
|
return -1;
|
|
}
|
|
|
|
if (c != '\\') {
|
|
glyphs[i++] = bitmap_font_lookup_ascii(font, c);
|
|
continue;
|
|
}
|
|
|
|
q = p;
|
|
while (*q) {
|
|
if ((*q == '\\') || (*q == ' '))
|
|
break;
|
|
q++;
|
|
}
|
|
if (q == p) {
|
|
glyphs[i++] = bitmap_font_lookup_ascii(font, *p++);
|
|
continue;
|
|
}
|
|
namelen = q - p;
|
|
if (*q == ' ')
|
|
q++;
|
|
|
|
glyphs[i++] = bitmap_font_lookup_glyph(font, p, namelen);
|
|
p = q;
|
|
}
|
|
|
|
*glyphp = glyphs;
|
|
return n;
|
|
|
|
}
|
|
|
|
static void
|
|
bitmap_font_text_size(const bitmap_font_t *font, const char *text,
|
|
int *width, int *height, int *ascent, int *descent)
|
|
{
|
|
const bitmap_glyph_t *glyph;
|
|
unsigned char *glyphs;
|
|
int i, n, w, a, d;
|
|
|
|
w = 0;
|
|
a = 0;
|
|
d = 0;
|
|
|
|
n = bitmap_font_text_to_glyphs(font, text, &glyphs);
|
|
|
|
for (i = 0; i < n; i++) {
|
|
glyph = &font->glyphs[glyphs[i]];
|
|
|
|
w += glyph->width;
|
|
|
|
if (glyph->ascent > a)
|
|
a = glyph->ascent;
|
|
if (glyph->descent < d)
|
|
d = glyph->descent;
|
|
}
|
|
|
|
*width = w - 1;
|
|
*height = font->ascent - font->descent;
|
|
*ascent = a;
|
|
*descent = d;
|
|
|
|
if (n > 0) {
|
|
free(glyphs);
|
|
}
|
|
}
|
|
|
|
static void
|
|
bitmap_font_draw_text(GdkDrawable *drawable, GdkColor *color,
|
|
const bitmap_font_t *font,
|
|
int x, int y, const char *text)
|
|
{
|
|
const bitmap_glyph_t *glyph;
|
|
unsigned char *glyphs;
|
|
GdkBitmap *bitmap;
|
|
GdkGC *gc;
|
|
int i, n, w, h;
|
|
|
|
gc = gdk_gc_new(drawable);
|
|
gdk_gc_set_rgb_fg_color(gc, color);
|
|
|
|
n = bitmap_font_text_to_glyphs(font, text, &glyphs);
|
|
|
|
for (i = 0; i < n; i++) {
|
|
glyph = &font->glyphs[glyphs[i]];
|
|
|
|
w = glyph->width - glyph->kern;
|
|
h = glyph->ascent - glyph->descent;
|
|
|
|
if (w <= 0 || h <= 0) {
|
|
x += glyph->width;
|
|
continue;
|
|
}
|
|
|
|
bitmap = gdk_bitmap_create_from_data(NULL, (char *) glyph->bits, w, h);
|
|
|
|
gdk_gc_set_ts_origin(gc, x + glyph->kern,
|
|
y + font->ascent - glyph->ascent);
|
|
gdk_gc_set_stipple(gc, bitmap);
|
|
gdk_gc_set_fill(gc, GDK_STIPPLED);
|
|
|
|
gdk_draw_rectangle(drawable, gc, TRUE, x + glyph->kern,
|
|
y + font->ascent - glyph->ascent, w, h);
|
|
|
|
g_object_unref(bitmap);
|
|
|
|
x += glyph->width;
|
|
}
|
|
|
|
g_object_unref(gc);
|
|
|
|
if (n > 0) {
|
|
free(glyphs);
|
|
}
|
|
}
|
|
|
|
static void
|
|
x49gp_ui_choose_file(x49gp_t *x49gp, const char *prompt,
|
|
GtkFileChooserAction action, char **filename)
|
|
{
|
|
GtkWidget *dialog;
|
|
x49gp_ui_t *ui = x49gp->ui;
|
|
|
|
dialog = gtk_file_chooser_dialog_new(prompt, GTK_WINDOW(ui->window),
|
|
action,
|
|
GTK_STOCK_CANCEL,
|
|
GTK_RESPONSE_CANCEL,
|
|
GTK_STOCK_OPEN,
|
|
GTK_RESPONSE_ACCEPT,
|
|
NULL);
|
|
|
|
gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dialog), TRUE);
|
|
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE);
|
|
|
|
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
|
*filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
|
} else {
|
|
*filename = NULL;
|
|
}
|
|
|
|
gtk_widget_destroy(dialog);
|
|
}
|
|
|
|
static gboolean
|
|
x49gp_ui_button_press(GtkWidget *widget, GdkEventButton *event,
|
|
gpointer user_data)
|
|
{
|
|
x49gp_ui_button_t *button = user_data;
|
|
const x49gp_ui_key_t *key = button->key;
|
|
x49gp_t *x49gp = button->x49gp;
|
|
x49gp_ui_t *ui = x49gp->ui;
|
|
|
|
#ifdef DEBUG_X49GP_UI
|
|
fprintf(stderr, "%s:%u: type %u, button %u\n", __FUNCTION__, __LINE__, event->type, event->button);
|
|
#endif
|
|
|
|
if (event->type != GDK_BUTTON_PRESS)
|
|
return FALSE;
|
|
|
|
switch (event->button) {
|
|
case 1:
|
|
ui->buttons_down++;
|
|
if (button->down) return FALSE;
|
|
button->down = TRUE;
|
|
break;
|
|
case 3:
|
|
button->hold = TRUE;
|
|
if (button->down) return FALSE;
|
|
gtk_button_pressed(GTK_BUTTON(button->button));
|
|
button->down = TRUE;
|
|
break;
|
|
default:
|
|
return TRUE;
|
|
}
|
|
|
|
#ifdef DEBUG_X49GP_UI
|
|
printf("%s: button %u: col %u, row %u, eint %u\n", __FUNCTION__,
|
|
event->button,
|
|
button->key->column, button->key->row, button->key->eint);
|
|
#endif
|
|
|
|
if (key->rowbit) {
|
|
s3c2410_io_port_g_update(x49gp, key->column, key->row, key->columnbit, key->rowbit, 1);
|
|
|
|
} else {
|
|
s3c2410_io_port_f_set_bit(x49gp, key->eint, 1);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
x49gp_release_single_button(x49gp_ui_button_t *button, x49gp_ui_button_t *cause)
|
|
{
|
|
x49gp_t *x49gp = button->x49gp;
|
|
const x49gp_ui_key_t *key;
|
|
GtkButton *gtkbutton;
|
|
|
|
#ifdef DEBUG_X49GP_UI
|
|
printf("%s: button %u: col %u, row %u, eint %u\n", __FUNCTION__,
|
|
event->button,
|
|
button->key->column, button->key->row, button->key->eint);
|
|
#endif
|
|
|
|
button->down = FALSE;
|
|
button->hold = FALSE;
|
|
|
|
gtkbutton = GTK_BUTTON(button->button);
|
|
|
|
if (button != cause)
|
|
gtkbutton->in_button = FALSE;
|
|
gtk_button_released(gtkbutton);
|
|
|
|
key = button->key;
|
|
|
|
if (key->rowbit) {
|
|
s3c2410_io_port_g_update(x49gp, key->column, key->row, key->columnbit, key->rowbit, 0);
|
|
|
|
} else {
|
|
s3c2410_io_port_f_set_bit(x49gp, key->eint, 0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
x49gp_release_all_buttons(x49gp_t *x49gp, x49gp_ui_button_t *cause)
|
|
{
|
|
x49gp_ui_button_t *button;
|
|
x49gp_ui_t *ui = x49gp->ui;
|
|
int i;
|
|
|
|
for (i = 0; i < ui->nr_buttons; i++) {
|
|
button = &ui->buttons[i];
|
|
|
|
if (! button->down)
|
|
continue;
|
|
|
|
x49gp_release_single_button(button, cause);
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
x49gp_ui_button_release(GtkWidget *widget, GdkEventButton *event,
|
|
gpointer user_data)
|
|
{
|
|
x49gp_ui_button_t *button = user_data;
|
|
x49gp_t *x49gp = button->x49gp;
|
|
x49gp_ui_t *ui = x49gp->ui;
|
|
|
|
if (event->type != GDK_BUTTON_RELEASE)
|
|
return FALSE;
|
|
|
|
switch (event->button) {
|
|
case 1:
|
|
break;
|
|
default:
|
|
return TRUE;
|
|
}
|
|
|
|
if (ui->buttons_down > 0)
|
|
ui->buttons_down--;
|
|
|
|
if (ui->buttons_down == 0) {
|
|
x49gp_release_all_buttons(x49gp, button);
|
|
} else {
|
|
x49gp_release_single_button(button, button);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean
|
|
x49gp_ui_show_menu(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
|
|
{
|
|
x49gp_t *x49gp = user_data;
|
|
x49gp_ui_t *ui = x49gp->ui;
|
|
|
|
gtk_widget_set_sensitive(ui->menu_unmount,
|
|
s3c2410_sdi_is_mounted(x49gp));
|
|
if (ui->menu_debug)
|
|
gtk_widget_set_sensitive(ui->menu_debug,
|
|
! gdbserver_isactive());
|
|
|
|
if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
|
|
gtk_menu_popup(GTK_MENU(ui->menu), NULL, NULL, NULL, NULL,
|
|
event->button, event->time);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean
|
|
x49gp_ui_button_leave(GtkWidget *widget, GdkEventCrossing *event,
|
|
gpointer user_data)
|
|
{
|
|
x49gp_ui_button_t *button = user_data;
|
|
|
|
if (event->type != GDK_LEAVE_NOTIFY)
|
|
return FALSE;
|
|
|
|
if (!button->hold)
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
x49gp_ui_focus_lost(GtkWidget *widget, GdkEventFocus *event,
|
|
gpointer user_data)
|
|
{
|
|
x49gp_t *x49gp = user_data;
|
|
x49gp_ui_t *ui = x49gp->ui;
|
|
|
|
if (event->type != GDK_FOCUS_CHANGE)
|
|
return FALSE;
|
|
|
|
ui->buttons_down = 0;
|
|
x49gp_release_all_buttons(x49gp, NULL);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
x49gp_ui_popup_at_widget(GtkMenu *menu, gint *x, gint *y, gboolean *push_in,
|
|
gpointer user_data)
|
|
{
|
|
GtkWidget *widget = GTK_WIDGET(user_data);
|
|
|
|
gdk_window_get_origin(widget->window, x, y);
|
|
*x += widget->allocation.x;
|
|
*y += widget->allocation.y;
|
|
}
|
|
|
|
static void
|
|
x49gp_ui_mount_sd_folder(GtkMenuItem *menuitem, gpointer user_data)
|
|
{
|
|
x49gp_t *x49gp = user_data;
|
|
char *filename;
|
|
|
|
x49gp_ui_choose_file(x49gp, "Choose SD folder ...",
|
|
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, &filename);
|
|
if (filename != NULL) s3c2410_sdi_mount(x49gp, filename);
|
|
}
|
|
|
|
static void
|
|
x49gp_ui_mount_sd_image(GtkMenuItem *menuitem, gpointer user_data)
|
|
{
|
|
x49gp_t *x49gp = user_data;
|
|
char *filename;
|
|
|
|
x49gp_ui_choose_file(x49gp, "Choose SD image ...",
|
|
GTK_FILE_CHOOSER_ACTION_OPEN, &filename);
|
|
if (filename != NULL) s3c2410_sdi_mount(x49gp, filename);
|
|
}
|
|
|
|
static void
|
|
x49gp_ui_debug(GtkMenuItem *menuitem, gpointer user_data)
|
|
{
|
|
x49gp_t *x49gp = user_data;
|
|
|
|
if(x49gp->debug_port != 0 && ! gdbserver_isactive()) {
|
|
gdbserver_start(x49gp->debug_port);
|
|
gdb_handlesig(x49gp->env, 0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
x49gp_ui_calculator_reset(GtkMenuItem *menuitem, gpointer user_data)
|
|
{
|
|
x49gp_t *x49gp = user_data;
|
|
|
|
x49gp_modules_reset(x49gp, X49GP_RESET_POWER_ON);
|
|
cpu_reset(x49gp->env);
|
|
x49gp_set_idle(x49gp, 0);
|
|
}
|
|
|
|
static gboolean
|
|
x49gp_ui_key_event(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
|
|
{
|
|
x49gp_t *x49gp = user_data;
|
|
x49gp_ui_t *ui = x49gp->ui;
|
|
x49gp_ui_button_t *button;
|
|
GdkEventButton bev;
|
|
gboolean save_in;
|
|
int index;
|
|
guint keyval;
|
|
|
|
#ifdef DEBUG_X49GP_UI
|
|
fprintf(stderr, "%s:%u: type %u, keyval %04x\n", __FUNCTION__, __LINE__, event->type, event->keyval);
|
|
#endif
|
|
/* We want to know the keyval as interpreted without modifiers. */
|
|
/* However, there is one modifier we do care about: NumLock, */
|
|
/* which normally is represented by MOD2. */
|
|
if (! gdk_keymap_translate_keyboard_state(gdk_keymap_get_default(),
|
|
event->hardware_keycode,
|
|
event->state & GDK_MOD2_MASK,
|
|
event->group,
|
|
&keyval, NULL, NULL, NULL))
|
|
return FALSE;
|
|
#ifdef DEBUG_X49GP_UI
|
|
fprintf(stderr, "%s:%u: state %u, base keyval %04x\n", __FUNCTION__, __LINE__, event->state, keyval);
|
|
#endif
|
|
|
|
switch (keyval) {
|
|
case GDK_KEY_a: case GDK_KEY_F1: index = 0; break;
|
|
case GDK_KEY_b: case GDK_KEY_F2: index = 1; break;
|
|
case GDK_KEY_c: case GDK_KEY_F3: index = 2; break;
|
|
case GDK_KEY_d: case GDK_KEY_F4: index = 3; break;
|
|
case GDK_KEY_e: case GDK_KEY_F5: index = 4; break;
|
|
case GDK_KEY_f: case GDK_KEY_F6: index = 5; break;
|
|
case GDK_KEY_g: index = 6; break;
|
|
case GDK_KEY_h: index = 7; break;
|
|
case GDK_KEY_i: index = 8; break;
|
|
case GDK_KEY_j: index = 9; break;
|
|
case GDK_KEY_k: index = 10; break;
|
|
case GDK_KEY_l: index = 11; break;
|
|
case GDK_KEY_Up: case GDK_KEY_KP_Up: index = 12; break;
|
|
case GDK_KEY_Left: case GDK_KEY_KP_Left: index = 13; break;
|
|
case GDK_KEY_Down: case GDK_KEY_KP_Down: index = 14; break;
|
|
case GDK_KEY_Right: case GDK_KEY_KP_Right: index = 15; break;
|
|
case GDK_KEY_m: index = 16; break;
|
|
case GDK_KEY_n: index = 17; break;
|
|
case GDK_KEY_o: case GDK_KEY_apostrophe: index = 18; break;
|
|
case GDK_KEY_p: index = 19; break;
|
|
case GDK_KEY_BackSpace: case GDK_KEY_Delete:
|
|
case GDK_KEY_KP_Delete: index = 20; break;
|
|
case GDK_KEY_dead_circumflex: case GDK_KEY_asciicircum:
|
|
case GDK_KEY_q: case GDK_KEY_caret: index = 21; break;
|
|
case GDK_KEY_r: index = 22; break;
|
|
case GDK_KEY_s: index = 23; break;
|
|
case GDK_KEY_t: index = 24; break;
|
|
case GDK_KEY_u: index = 25; break;
|
|
case GDK_KEY_v: index = 26; break;
|
|
case GDK_KEY_w: index = 27; break;
|
|
case GDK_KEY_x: index = 28; break;
|
|
case GDK_KEY_y: index = 29; break;
|
|
case GDK_KEY_z:
|
|
case GDK_KEY_slash: case GDK_KEY_KP_Divide: index = 30; break;
|
|
case GDK_KEY_Tab: index = 31; break;
|
|
#ifndef __APPLE__
|
|
//case GDK_KEY_Alt_L: case GDK_KEY_Alt_R:
|
|
//case GDK_KEY_Meta_L: case GDK_KEY_Meta_R:
|
|
case GDK_KEY_Mode_switch: index = 31; break;
|
|
#endif
|
|
case GDK_KEY_7: case GDK_KEY_KP_7: index = 32; break;
|
|
case GDK_KEY_8: case GDK_KEY_KP_8: index = 33; break;
|
|
case GDK_KEY_9: case GDK_KEY_KP_9: index = 34; break;
|
|
case GDK_KEY_multiply: case GDK_KEY_KP_Multiply: index = 35; break;
|
|
case GDK_KEY_Shift_L: case GDK_KEY_Shift_R: index = 36; break;
|
|
case GDK_KEY_4: case GDK_KEY_KP_4: index = 37; break;
|
|
case GDK_KEY_5: case GDK_KEY_KP_5: index = 38; break;
|
|
case GDK_KEY_6: case GDK_KEY_KP_6: index = 39; break;
|
|
case GDK_KEY_minus: case GDK_KEY_KP_Subtract: index = 40; break;
|
|
case GDK_KEY_Control_L: case GDK_KEY_Control_R: index = 41; break;
|
|
case GDK_KEY_1: case GDK_KEY_KP_1: index = 42; break;
|
|
case GDK_KEY_2: case GDK_KEY_KP_2: index = 43; break;
|
|
case GDK_KEY_3: case GDK_KEY_KP_3: index = 44; break;
|
|
case GDK_KEY_plus: case GDK_KEY_KP_Add: index = 45; break;
|
|
case GDK_KEY_Escape: index = 46; break;
|
|
case GDK_KEY_0: case GDK_KEY_KP_0: index = 47; break;
|
|
case GDK_KEY_period: case GDK_KEY_comma:
|
|
case GDK_KEY_KP_Decimal: case GDK_KP_Separator: index = 48; break;
|
|
case GDK_KEY_space: case GDK_KEY_KP_Space: index = 49; break;
|
|
case GDK_KEY_Return: case GDK_KEY_KP_Enter: index = 50; break;
|
|
|
|
/* QUERTY compat: US English, UK English, International English */
|
|
case GDK_KEY_backslash: index = 35; break;
|
|
case GDK_KEY_equal: index = 45; break;
|
|
|
|
/* QUERTZ compat: German */
|
|
case GDK_KEY_ssharp: index = 30; break;
|
|
case GDK_KEY_numbersign: index = 35; break;
|
|
|
|
case GDK_KEY_F12:
|
|
switch (event->type) {
|
|
case GDK_KEY_PRESS:
|
|
x49gp_modules_reset(x49gp, X49GP_RESET_POWER_ON);
|
|
cpu_reset(x49gp->env);
|
|
x49gp_set_idle(x49gp, 1);
|
|
break;
|
|
case GDK_KEY_RELEASE:
|
|
x49gp_set_idle(x49gp, 0);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return FALSE;
|
|
|
|
case GDK_KEY_Menu:
|
|
gtk_widget_set_sensitive(ui->menu_unmount,
|
|
s3c2410_sdi_is_mounted(x49gp));
|
|
if (ui->menu_debug)
|
|
gtk_widget_set_sensitive(ui->menu_debug,
|
|
! gdbserver_isactive());
|
|
|
|
gtk_menu_popup(GTK_MENU(ui->menu), NULL, NULL,
|
|
x49gp_ui_popup_at_widget, ui->lcd_canvas,
|
|
0, event->time);
|
|
return FALSE;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
button = &ui->buttons[index];
|
|
|
|
memset(&bev, 0, sizeof(GdkEventButton));
|
|
|
|
bev.time = event->time;
|
|
bev.button = 1;
|
|
bev.state = event->state;
|
|
|
|
save_in = GTK_BUTTON(button->button)->in_button;
|
|
|
|
switch (event->type) {
|
|
case GDK_KEY_PRESS:
|
|
bev.type = GDK_BUTTON_PRESS;
|
|
x49gp_ui_button_press(button->button, &bev, button);
|
|
GTK_BUTTON(button->button)->in_button = TRUE;
|
|
gtk_button_pressed(GTK_BUTTON(button->button));
|
|
GTK_BUTTON(button->button)->in_button = save_in;
|
|
break;
|
|
case GDK_KEY_RELEASE:
|
|
bev.type = GDK_BUTTON_RELEASE;
|
|
GTK_BUTTON(button->button)->in_button = TRUE;
|
|
gtk_button_released(GTK_BUTTON(button->button));
|
|
GTK_BUTTON(button->button)->in_button = save_in;
|
|
x49gp_ui_button_release(button->button, &bev, button);
|
|
break;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static int
|
|
x49gp_button_expose_event(GtkWidget *widget, GdkEventExpose *event,
|
|
gpointer user_data)
|
|
{
|
|
x49gp_ui_button_t *button = user_data;
|
|
int x, y;
|
|
|
|
x = widget->allocation.x;
|
|
y = widget->allocation.y;
|
|
|
|
if (GTK_WIDGET_STATE(widget) == GTK_STATE_ACTIVE)
|
|
y -= 1;
|
|
|
|
gdk_draw_drawable(widget->window, widget->style->black_gc,
|
|
button->pixmap, 0, 0, x, y,
|
|
widget->allocation.width, widget->allocation.height);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
x49gp_button_realize(GtkWidget *widget, gpointer user_data)
|
|
{
|
|
x49gp_ui_button_t *button = user_data;
|
|
x49gp_ui_t *ui = button->x49gp->ui;
|
|
const x49gp_ui_key_t *key = button->key;
|
|
cairo_t *cr;
|
|
double xoff, yoff, width, height, ascent, descent;
|
|
unsigned int w, h;
|
|
int xoffset, yoffset, x, y;
|
|
|
|
xoffset = widget->allocation.x;
|
|
yoffset = widget->allocation.y;
|
|
w = widget->allocation.width;
|
|
h = widget->allocation.height;
|
|
|
|
button->pixmap = gdk_pixmap_new(widget->style->bg_pixmap[0], w, h, -1);
|
|
|
|
gdk_draw_drawable(button->pixmap, widget->style->black_gc,
|
|
widget->style->bg_pixmap[0],
|
|
xoffset, yoffset,
|
|
0, 0, button->key->width, button->key->height);
|
|
|
|
xoffset += 2;
|
|
yoffset += 2;
|
|
w -= 4;
|
|
h -= 4;
|
|
|
|
cr = gdk_cairo_create(button->pixmap);
|
|
cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
|
|
cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER);
|
|
|
|
#if 0 /* Layout Debug */
|
|
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
|
|
cairo_set_line_width(cr, 1.0);
|
|
cairo_move_to(cr, xoffset, yoffset);
|
|
cairo_line_to(cr, xoffset + w - 1, yoffset);
|
|
cairo_line_to(cr, xoffset + w - 1, yoffset + h - 1);
|
|
cairo_line_to(cr, xoffset, yoffset + h - 1);
|
|
cairo_close_path(cr);
|
|
cairo_stroke(cr);
|
|
#endif
|
|
|
|
if (key->letter) {
|
|
x49gp_ui_text_size(cr, X49GP_UI_NORMAL_FONT, key->letter_size,
|
|
&xoff, &yoff, &width, &height, &ascent, &descent,
|
|
1, CAIRO_FONT_SLANT_NORMAL, key->font_weight,
|
|
key->letter);
|
|
|
|
switch (key->layout) {
|
|
case UI_LAYOUT_LEFT:
|
|
default:
|
|
x = (int) floor(w - 1.0 - width - xoff + 0.5);
|
|
y = (int) floor((h - 1.0 + ascent) / 2.0 + 0.5);
|
|
w -= width;
|
|
break;
|
|
case UI_LAYOUT_LEFT_NO_SPACE:
|
|
x = (int) floor(w - 1.0 - width - xoff + 0.5);
|
|
y = (int) floor((h - 1.0 + ascent) / 2.0 + 0.5);
|
|
break;
|
|
case UI_LAYOUT_BELOW:
|
|
x = (int) floor((w - 1.0 - width) / 2.0 - xoff + 0.5);
|
|
y = (int) h - 1.0;
|
|
h -= ascent;
|
|
break;
|
|
}
|
|
|
|
x49gp_ui_draw_text(cr, &ui->colors[UI_COLOR_YELLOW],
|
|
X49GP_UI_NORMAL_FONT, key->letter_size, 0.0,
|
|
x + xoffset, y + yoffset,
|
|
1, CAIRO_FONT_SLANT_NORMAL, key->font_weight,
|
|
key->letter);
|
|
}
|
|
|
|
x49gp_ui_text_size(cr, X49GP_UI_NORMAL_FONT, key->font_size,
|
|
&xoff, &yoff, &width, &height, &ascent, &descent,
|
|
1, CAIRO_FONT_SLANT_NORMAL, key->font_weight,
|
|
key->label);
|
|
|
|
x = (int) floor((w - 1.0 - width) / 2.0 - xoff + 0.5);
|
|
y = (int) floor((h - 1.0 + ascent) / 2.0 + 0.5);
|
|
|
|
x49gp_ui_draw_text(cr, &widget->style->text[0],
|
|
X49GP_UI_NORMAL_FONT, key->font_size, 0.0,
|
|
x + xoffset, y + yoffset,
|
|
1, CAIRO_FONT_SLANT_NORMAL, key->font_weight,
|
|
key->label);
|
|
|
|
cairo_destroy(cr);
|
|
}
|
|
|
|
static int
|
|
x49gp_lcd_expose_event(GtkWidget *widget, GdkEventExpose *event,
|
|
gpointer user_data)
|
|
{
|
|
x49gp_t *x49gp = user_data;
|
|
x49gp_ui_t *ui = x49gp->ui;
|
|
GdkRectangle *rects;
|
|
int i, n;
|
|
|
|
gdk_region_get_rectangles(event->region, &rects, &n);
|
|
for (i = 0; i < n; i++) {
|
|
gdk_draw_drawable(widget->window, widget->style->black_gc,
|
|
ui->lcd_pixmap,
|
|
rects[i].x, rects[i].y,
|
|
rects[i].x, rects[i].y,
|
|
rects[i].width, rects[i].height);
|
|
}
|
|
g_free(rects);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static int
|
|
x49gp_lcd_configure_event(GtkWidget *widget, GdkEventConfigure *event,
|
|
gpointer user_data)
|
|
{
|
|
x49gp_t *x49gp = user_data;
|
|
x49gp_ui_t *ui = x49gp->ui;
|
|
|
|
if (NULL != ui->lcd_pixmap) {
|
|
return FALSE;
|
|
}
|
|
|
|
ui->ann_left = gdk_bitmap_create_from_data(ui->lcd_canvas->window,
|
|
(char *) ann_left_bits,
|
|
ann_left_width,
|
|
ann_left_height);
|
|
ui->ann_right = gdk_bitmap_create_from_data(ui->lcd_canvas->window,
|
|
(char *) ann_right_bits,
|
|
ann_right_width,
|
|
ann_right_height);
|
|
ui->ann_alpha = gdk_bitmap_create_from_data(ui->lcd_canvas->window,
|
|
(char *) ann_alpha_bits,
|
|
ann_alpha_width,
|
|
ann_alpha_height);
|
|
ui->ann_battery = gdk_bitmap_create_from_data(ui->lcd_canvas->window,
|
|
(char *) ann_battery_bits,
|
|
ann_battery_width,
|
|
ann_battery_height);
|
|
ui->ann_busy = gdk_bitmap_create_from_data(ui->lcd_canvas->window,
|
|
(char *) ann_busy_bits,
|
|
ann_busy_width,
|
|
ann_busy_height);
|
|
ui->ann_io = gdk_bitmap_create_from_data(ui->lcd_canvas->window,
|
|
(char *) ann_io_bits,
|
|
ann_io_width,
|
|
ann_io_height);
|
|
|
|
ui->ann_left_gc = gdk_gc_new(ui->lcd_canvas->window);
|
|
gdk_gc_copy(ui->ann_left_gc, widget->style->black_gc);
|
|
gdk_gc_set_ts_origin(ui->ann_left_gc, 11, 0);
|
|
gdk_gc_set_stipple(ui->ann_left_gc, ui->ann_left);
|
|
gdk_gc_set_fill(ui->ann_left_gc, GDK_STIPPLED);
|
|
|
|
ui->ann_right_gc = gdk_gc_new(ui->lcd_canvas->window);
|
|
gdk_gc_copy(ui->ann_right_gc, widget->style->black_gc);
|
|
gdk_gc_set_ts_origin(ui->ann_right_gc, 56, 0);
|
|
gdk_gc_set_stipple(ui->ann_right_gc, ui->ann_right);
|
|
gdk_gc_set_fill(ui->ann_right_gc, GDK_STIPPLED);
|
|
|
|
ui->ann_alpha_gc = gdk_gc_new(ui->lcd_canvas->window);
|
|
gdk_gc_copy(ui->ann_alpha_gc, widget->style->black_gc);
|
|
gdk_gc_set_ts_origin(ui->ann_alpha_gc, 101, 0);
|
|
gdk_gc_set_stipple(ui->ann_alpha_gc, ui->ann_alpha);
|
|
gdk_gc_set_fill(ui->ann_alpha_gc, GDK_STIPPLED);
|
|
|
|
ui->ann_battery_gc = gdk_gc_new(ui->lcd_canvas->window);
|
|
gdk_gc_copy(ui->ann_battery_gc, widget->style->black_gc);
|
|
gdk_gc_set_ts_origin(ui->ann_battery_gc, 146, 0);
|
|
gdk_gc_set_stipple(ui->ann_battery_gc, ui->ann_battery);
|
|
gdk_gc_set_fill(ui->ann_battery_gc, GDK_STIPPLED);
|
|
|
|
ui->ann_busy_gc = gdk_gc_new(ui->lcd_canvas->window);
|
|
gdk_gc_copy(ui->ann_busy_gc, widget->style->black_gc);
|
|
gdk_gc_set_ts_origin(ui->ann_busy_gc, 191, 0);
|
|
gdk_gc_set_stipple(ui->ann_busy_gc, ui->ann_busy);
|
|
gdk_gc_set_fill(ui->ann_busy_gc, GDK_STIPPLED);
|
|
|
|
ui->ann_io_gc = gdk_gc_new(ui->lcd_canvas->window);
|
|
gdk_gc_copy(ui->ann_io_gc, widget->style->black_gc);
|
|
gdk_gc_set_ts_origin(ui->ann_io_gc, 236, 0);
|
|
gdk_gc_set_stipple(ui->ann_io_gc, ui->ann_io);
|
|
gdk_gc_set_fill(ui->ann_io_gc, GDK_STIPPLED);
|
|
|
|
|
|
ui->lcd_pixmap = gdk_pixmap_new(ui->lcd_canvas->window,
|
|
ui->lcd_width, ui->lcd_height, -1);
|
|
|
|
#if 0 /* Debug Symbols on LCD screen ;) */
|
|
{
|
|
cairo_t *cr;
|
|
|
|
cr = gdk_cairo_create(ui->bg_pixmap);
|
|
cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
|
|
cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER);
|
|
|
|
#if 1
|
|
x49gp_ui_draw_text(cr, &widget->style->black,
|
|
X49GP_UI_NORMAL_FONT, 100.0, 1.0,
|
|
ui->lcd_x_offset + 10, ui->lcd_y_offset + 160,
|
|
1, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD,
|
|
"\\arrowleftdblfull");
|
|
#else
|
|
x49gp_ui_dump_path(cr, X49GP_UI_NORMAL_FONT,
|
|
1, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD,
|
|
"\\arrowleftdblfull");
|
|
#endif
|
|
|
|
cairo_destroy(cr);
|
|
}
|
|
#endif
|
|
|
|
gdk_draw_drawable(ui->lcd_pixmap, widget->style->black_gc,
|
|
ui->bg_pixmap, ui->lcd_x_offset, ui->lcd_y_offset,
|
|
0, 0, ui->lcd_width, ui->lcd_height);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static int
|
|
x49gp_window_configure_event(GtkWidget *widget, GdkEventConfigure *event,
|
|
gpointer user_data)
|
|
{
|
|
x49gp_t *x49gp = user_data;
|
|
x49gp_ui_t *ui = x49gp->ui;
|
|
const x49gp_ui_key_t *key;
|
|
cairo_t *cr;
|
|
int left_color;
|
|
int right_color;
|
|
int below_color;
|
|
int xl, xr, a;
|
|
int wl = 0, wr = 0;
|
|
int hl = 0, hr = 0;
|
|
int dl = 0, dr = 0;
|
|
int i;
|
|
|
|
if (NULL != ui->bg_pixmap) {
|
|
return FALSE;
|
|
}
|
|
|
|
ui->bg_pixmap = gdk_pixmap_new(widget->window,
|
|
ui->width, ui->height, -1);
|
|
|
|
gdk_draw_pixbuf(ui->bg_pixmap, widget->style->black_gc,
|
|
ui->bg_pixbuf, 0, 0, 0, 0, ui->width, ui->height,
|
|
GDK_RGB_DITHER_NORMAL, 0, 0);
|
|
|
|
cr = gdk_cairo_create(ui->bg_pixmap);
|
|
cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
|
|
cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER);
|
|
|
|
switch (ui->calculator) {
|
|
default:
|
|
ui->calculator = UI_CALCULATOR_HP49GP;
|
|
/* fall through */
|
|
|
|
case UI_CALCULATOR_HP49GP:
|
|
x49gp_ui_draw_text(cr, &widget->style->black,
|
|
X49GP_UI_NORMAL_FONT, 15.0, 0.0,
|
|
38, 42, 2,
|
|
CAIRO_FONT_SLANT_NORMAL,
|
|
CAIRO_FONT_WEIGHT_BOLD,
|
|
"hp",
|
|
CAIRO_FONT_SLANT_NORMAL,
|
|
CAIRO_FONT_WEIGHT_NORMAL,
|
|
" 49g+");
|
|
|
|
x49gp_ui_draw_text(cr, &widget->style->black,
|
|
X49GP_UI_NORMAL_FONT, 13.0, 0.0,
|
|
38, 56, 1,
|
|
CAIRO_FONT_SLANT_NORMAL,
|
|
CAIRO_FONT_WEIGHT_NORMAL,
|
|
"graphing calculator");
|
|
|
|
x49gp_ui_draw_symbol(cr, &widget->style->black, 10.0, 0.0, TRUE,
|
|
138, 25, symbol_get_by_name("triangleup"));
|
|
|
|
left_color = UI_COLOR_GREEN;
|
|
right_color = UI_COLOR_RED;
|
|
below_color = UI_COLOR_BLACK;
|
|
break;
|
|
|
|
case UI_CALCULATOR_HP50G:
|
|
x49gp_ui_draw_text(cr, &widget->style->white,
|
|
X49GP_UI_NORMAL_FONT, 15.0, 0.0,
|
|
38, 42, 2,
|
|
CAIRO_FONT_SLANT_NORMAL,
|
|
CAIRO_FONT_WEIGHT_NORMAL,
|
|
"HP",
|
|
CAIRO_FONT_SLANT_NORMAL,
|
|
CAIRO_FONT_WEIGHT_NORMAL,
|
|
" 50g");
|
|
|
|
x49gp_ui_draw_text(cr, &widget->style->white,
|
|
X49GP_UI_NORMAL_FONT, 13.0, 0.0,
|
|
38, 56, 1,
|
|
CAIRO_FONT_SLANT_NORMAL,
|
|
CAIRO_FONT_WEIGHT_NORMAL,
|
|
"Graphing Calculator");
|
|
|
|
x49gp_ui_draw_symbol(cr, &widget->style->white, 10.0, 0.0, TRUE,
|
|
168, 25, symbol_get_by_name("triangleup"));
|
|
|
|
left_color = UI_COLOR_WHITE;
|
|
right_color = UI_COLOR_ORANGE;
|
|
below_color = UI_COLOR_BLUE;
|
|
break;
|
|
}
|
|
|
|
cairo_destroy(cr);
|
|
|
|
for (i = 0; i < ui->nr_buttons; i++) {
|
|
key = &x49gp_ui_keys[i];
|
|
key = &x50g_ui_keys[i];
|
|
|
|
if (key->left) {
|
|
bitmap_font_text_size(&tiny_font, key->left, &wl, &hl, &a, &dl);
|
|
if (!key->right) {
|
|
xl = key->x + (key->width - wl) / 2;
|
|
bitmap_font_draw_text(ui->bg_pixmap,
|
|
&ui->colors[left_color],
|
|
&tiny_font,
|
|
ui->kb_x_offset + xl,
|
|
ui->kb_y_offset + key->y - hl + dl + 1,
|
|
key->left);
|
|
}
|
|
}
|
|
|
|
if (key->right) {
|
|
bitmap_font_text_size(&tiny_font, key->right, &wr, &hr, &a, &dr);
|
|
if (!key->left) {
|
|
xr = key->x + (key->width - wr) / 2;
|
|
bitmap_font_draw_text(ui->bg_pixmap,
|
|
&ui->colors[right_color],
|
|
&tiny_font,
|
|
ui->kb_x_offset + xr,
|
|
ui->kb_y_offset + key->y - hr + dr + 1,
|
|
key->right);
|
|
}
|
|
}
|
|
|
|
if (key->left && key->right) {
|
|
xl = key->x;
|
|
xr = key->x + key->width - 1 - wr;
|
|
|
|
if (wl + wr > key->width - 4) {
|
|
xl += (key->width - 4 - (wl + wr)) / 2;
|
|
xr -= (key->width - 4 - (wl + wr)) / 2;
|
|
}
|
|
|
|
bitmap_font_draw_text(ui->bg_pixmap,
|
|
&ui->colors[left_color],
|
|
&tiny_font,
|
|
ui->kb_x_offset + xl,
|
|
ui->kb_y_offset + key->y - hl + dl + 1,
|
|
key->left);
|
|
|
|
bitmap_font_draw_text(ui->bg_pixmap,
|
|
&ui->colors[right_color],
|
|
&tiny_font,
|
|
ui->kb_x_offset + xr,
|
|
ui->kb_y_offset + key->y - hr + dr + 1,
|
|
key->right);
|
|
}
|
|
|
|
if (key->below) {
|
|
bitmap_font_text_size(&tiny_font, key->below, &wl, &hl, &a, &dl);
|
|
xl = key->x + (key->width - wl) / 2;
|
|
|
|
bitmap_font_draw_text(ui->bg_pixmap,
|
|
&ui->colors[below_color],
|
|
&tiny_font,
|
|
ui->kb_x_offset + xl,
|
|
ui->kb_y_offset + key->y + key->height + 2,
|
|
key->below);
|
|
}
|
|
|
|
#if 0 /* Debug Button Layout */
|
|
gdk_draw_rectangle(ui->bg_pixmap, ui->window->style->white_gc,
|
|
FALSE,
|
|
ui->kb_x_offset + key->x,
|
|
ui->kb_y_offset + key->y,
|
|
key->width, key->height);
|
|
#endif
|
|
}
|
|
|
|
gdk_window_set_back_pixmap(widget->window, ui->bg_pixmap, FALSE);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean
|
|
x49gp_window_button_press(GtkWidget *widget, GdkEventButton *event,
|
|
gpointer user_data)
|
|
{
|
|
#ifdef DEBUG_X49GP_UI
|
|
fprintf(stderr, "%s:%u: type %u, button %u\n", __FUNCTION__, __LINE__, event->type, event->button);
|
|
#endif
|
|
|
|
gdk_window_focus(widget->window, event->time);
|
|
gdk_window_raise(widget->window);
|
|
|
|
if (event->type != GDK_BUTTON_PRESS)
|
|
return FALSE;
|
|
|
|
if (event->button != 1)
|
|
return FALSE;
|
|
|
|
gdk_window_begin_move_drag(widget->window, event->button,
|
|
event->x_root, event->y_root,
|
|
event->time);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
x49gp_ui_quit(gpointer user_data, GtkWidget *widget, GdkEvent *event)
|
|
{
|
|
x49gp_t *x49gp = user_data;
|
|
|
|
x49gp->arm_exit++;
|
|
}
|
|
|
|
static void
|
|
x49gp_ui_place_at(x49gp_t *x49gp, GtkFixed *fixed, GtkWidget *widget,
|
|
gint x, gint y, gint width, gint height)
|
|
{
|
|
gtk_widget_set_size_request(widget, width, height);
|
|
gtk_fixed_put(fixed, widget, x, y);
|
|
}
|
|
|
|
static int
|
|
gui_init(x49gp_module_t *module)
|
|
{
|
|
x49gp_t *x49gp = module->x49gp;
|
|
x49gp_ui_t *ui;
|
|
|
|
ui = malloc(sizeof(x49gp_ui_t));
|
|
if (NULL == ui) {
|
|
fprintf(stderr, "%s: %s:%u: Out of memory\n",
|
|
x49gp->progname, __FUNCTION__, __LINE__);
|
|
return -ENOMEM;
|
|
}
|
|
memset(ui, 0, sizeof(x49gp_ui_t));
|
|
|
|
ui->nr_buttons = X49GP_UI_NR_KEYS;
|
|
ui->buttons = malloc(ui->nr_buttons * sizeof(x49gp_ui_button_t));
|
|
if (NULL == ui->buttons) {
|
|
fprintf(stderr, "%s: %s:%u: Out of memory\n",
|
|
x49gp->progname, __FUNCTION__, __LINE__);
|
|
free(ui);
|
|
return -ENOMEM;
|
|
}
|
|
memset(ui->buttons, 0, ui->nr_buttons * sizeof(x49gp_ui_button_t));
|
|
|
|
module->user_data = ui;
|
|
x49gp->ui = ui;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
gui_exit(x49gp_module_t *module)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
gui_reset(x49gp_module_t *module, x49gp_reset_t reset)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
gui_load(x49gp_module_t *module, GKeyFile *keyfile)
|
|
{
|
|
x49gp_t *x49gp = module->x49gp;
|
|
x49gp_ui_t *ui = module->user_data;
|
|
x49gp_ui_button_t *button;
|
|
const x49gp_ui_key_t *key;
|
|
GtkWidget *screen_box;
|
|
GtkWidget *menu_mount_folder, *menu_mount_image, *menu_unmount;
|
|
GtkWidget *menu_debug, *menu_reset, *menu_quit;
|
|
GError *gerror = NULL;
|
|
GdkBitmap *shape;
|
|
char *typestr;
|
|
char *imagefile;
|
|
int fd;
|
|
int i;
|
|
|
|
x49gp_module_get_string(module, keyfile, "type", "hp50g", &typestr);
|
|
if (!strcmp(typestr, "hp49g+")) {
|
|
ui->calculator = UI_CALCULATOR_HP49GP;
|
|
} else if (!strcmp(typestr, "hp50g")) {
|
|
ui->calculator = UI_CALCULATOR_HP50G;
|
|
} else {
|
|
fprintf(stderr, "Invalid calculator type, reverting to default\n");
|
|
ui->calculator = UI_CALCULATOR_HP50G;
|
|
}
|
|
|
|
x49gp_module_get_string(module, keyfile, "name",
|
|
ui->calculator == UI_CALCULATOR_HP49GP ?
|
|
"HP 49g+" : "HP 50g",
|
|
&(ui->name));
|
|
|
|
fd = x49gp_module_open_rodata(module,
|
|
ui->calculator == UI_CALCULATOR_HP49GP ?
|
|
"hp49g+.png" : "hp50g.png",
|
|
&imagefile);
|
|
if (fd < 0) return fd;
|
|
|
|
gdk_pixbuf_get_file_info(imagefile, &ui->width, &ui->height);
|
|
|
|
ui->lcd_width = 131 * 2;
|
|
ui->lcd_top_margin = 16;
|
|
ui->lcd_height = 80 * 2 + ui->lcd_top_margin;
|
|
|
|
ui->lcd_x_offset = (ui->width - ui->lcd_width) / 2;
|
|
ui->lcd_y_offset = 69;
|
|
|
|
ui->kb_x_offset = 36;
|
|
ui->kb_y_offset = 301;
|
|
|
|
ui->bg_pixbuf = gdk_pixbuf_new_from_file(imagefile, &gerror);
|
|
close(fd);
|
|
|
|
|
|
ui->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
|
gtk_widget_set(ui->window, "can-focus", TRUE, NULL);
|
|
gtk_widget_set(ui->window, "accept-focus", TRUE, NULL);
|
|
gtk_widget_set(ui->window, "focus-on-map", TRUE, NULL);
|
|
gtk_widget_set(ui->window, "resizable", FALSE, NULL);
|
|
gtk_window_set_decorated(GTK_WINDOW(ui->window), FALSE);
|
|
|
|
gtk_widget_set_name(ui->window, ui->name);
|
|
gtk_window_set_title(GTK_WINDOW(ui->window), ui->name);
|
|
|
|
// gtk_window_set_icon(GTK_WINDOW(ui->window), ui->bg_pixbuf);
|
|
|
|
gdk_pixbuf_render_pixmap_and_mask(ui->bg_pixbuf, NULL, &shape, 255);
|
|
|
|
gtk_widget_set_size_request(ui->window, ui->width, ui->height);
|
|
gtk_widget_shape_combine_mask(ui->window, shape, 0, 0);
|
|
|
|
g_object_unref(shape);
|
|
|
|
gtk_widget_realize(ui->window);
|
|
|
|
ui->shapes[UI_SHAPE_BUTTON_TINY] = gdk_bitmap_create_from_data(NULL,
|
|
(char *) button_tiny_bits,
|
|
button_tiny_width,
|
|
button_tiny_height);
|
|
ui->shapes[UI_SHAPE_BUTTON_SMALL] = gdk_bitmap_create_from_data(NULL,
|
|
(char *) button_small_bits,
|
|
button_small_width,
|
|
button_small_height);
|
|
ui->shapes[UI_SHAPE_BUTTON_NORMAL] = gdk_bitmap_create_from_data(NULL,
|
|
(char *) button_normal_bits,
|
|
button_normal_width,
|
|
button_normal_height);
|
|
ui->shapes[UI_SHAPE_BUTTON_LARGE] = gdk_bitmap_create_from_data(NULL,
|
|
(char *) button_large_bits,
|
|
button_large_width,
|
|
button_large_height);
|
|
ui->shapes[UI_SHAPE_BUTTON_ROUND] = gdk_bitmap_create_from_data(NULL,
|
|
(char *) button_round_bits,
|
|
button_round_width,
|
|
button_round_height);
|
|
|
|
|
|
ui->fixed = gtk_fixed_new();
|
|
gtk_container_add(GTK_CONTAINER(ui->window), ui->fixed);
|
|
|
|
ui->background = gtk_drawing_area_new();
|
|
gtk_drawing_area_size(GTK_DRAWING_AREA(ui->background),
|
|
ui->width, ui->height);
|
|
x49gp_ui_place_at(x49gp, GTK_FIXED(ui->fixed), ui->background,
|
|
0, 0, ui->width, ui->height);
|
|
|
|
x49gp_ui_color_init(&ui->colors[UI_COLOR_BLACK], 0x00, 0x00, 0x00);
|
|
x49gp_ui_color_init(&ui->colors[UI_COLOR_WHITE], 0xff, 0xff, 0xff);
|
|
x49gp_ui_color_init(&ui->colors[UI_COLOR_YELLOW], 0xfa, 0xe8, 0x2c);
|
|
x49gp_ui_color_init(&ui->colors[UI_COLOR_RED], 0x8e, 0x25, 0x18);
|
|
x49gp_ui_color_init(&ui->colors[UI_COLOR_GREEN], 0x14, 0x4d, 0x49);
|
|
x49gp_ui_color_init(&ui->colors[UI_COLOR_SILVER], 0xe0, 0xe0, 0xe0);
|
|
x49gp_ui_color_init(&ui->colors[UI_COLOR_ORANGE], 0xc0, 0x6e, 0x60);
|
|
x49gp_ui_color_init(&ui->colors[UI_COLOR_BLUE], 0x40, 0x60, 0xa4);
|
|
|
|
x49gp_ui_color_init(&ui->colors[UI_COLOR_GRAYSCALE_0], 0xab, 0xd2, 0xb4);
|
|
x49gp_ui_color_init(&ui->colors[UI_COLOR_GRAYSCALE_1], 0xa0, 0xc4, 0xa8);
|
|
x49gp_ui_color_init(&ui->colors[UI_COLOR_GRAYSCALE_2], 0x94, 0xb6, 0x9c);
|
|
x49gp_ui_color_init(&ui->colors[UI_COLOR_GRAYSCALE_3], 0x89, 0xa8, 0x90);
|
|
x49gp_ui_color_init(&ui->colors[UI_COLOR_GRAYSCALE_4], 0x7d, 0x9a, 0x84);
|
|
x49gp_ui_color_init(&ui->colors[UI_COLOR_GRAYSCALE_5], 0x72, 0x8c, 0x78);
|
|
x49gp_ui_color_init(&ui->colors[UI_COLOR_GRAYSCALE_6], 0x67, 0x7e, 0x6c);
|
|
x49gp_ui_color_init(&ui->colors[UI_COLOR_GRAYSCALE_7], 0x5b, 0x70, 0x60);
|
|
x49gp_ui_color_init(&ui->colors[UI_COLOR_GRAYSCALE_8], 0x50, 0x62, 0x54);
|
|
x49gp_ui_color_init(&ui->colors[UI_COLOR_GRAYSCALE_9], 0x44, 0x54, 0x48);
|
|
x49gp_ui_color_init(&ui->colors[UI_COLOR_GRAYSCALE_10], 0x39, 0x46, 0x3c);
|
|
x49gp_ui_color_init(&ui->colors[UI_COLOR_GRAYSCALE_11], 0x2e, 0x38, 0x30);
|
|
x49gp_ui_color_init(&ui->colors[UI_COLOR_GRAYSCALE_12], 0x22, 0x2a, 0x24);
|
|
x49gp_ui_color_init(&ui->colors[UI_COLOR_GRAYSCALE_13], 0x17, 0x1c, 0x18);
|
|
x49gp_ui_color_init(&ui->colors[UI_COLOR_GRAYSCALE_14], 0x0b, 0x03, 0x0c);
|
|
x49gp_ui_color_init(&ui->colors[UI_COLOR_GRAYSCALE_15], 0x00, 0x00, 0x00);
|
|
|
|
|
|
ui->lcd_canvas = gtk_drawing_area_new();
|
|
gtk_drawing_area_size(GTK_DRAWING_AREA(ui->lcd_canvas),
|
|
ui->lcd_width, ui->lcd_height);
|
|
screen_box = gtk_event_box_new();
|
|
gtk_event_box_set_visible_window(GTK_EVENT_BOX(screen_box),
|
|
TRUE);
|
|
gtk_event_box_set_above_child(GTK_EVENT_BOX(screen_box),
|
|
FALSE);
|
|
gtk_container_add(GTK_CONTAINER(screen_box), ui->lcd_canvas);
|
|
x49gp_ui_place_at(x49gp, GTK_FIXED(ui->fixed), screen_box,
|
|
ui->lcd_x_offset, ui->lcd_y_offset,
|
|
ui->lcd_width, ui->lcd_height);
|
|
|
|
|
|
for (i = 0; i < ui->nr_buttons; i++) {
|
|
key = &x49gp_ui_keys[i];
|
|
key = &x50g_ui_keys[i];
|
|
button = &ui->buttons[i];
|
|
|
|
button->x49gp = x49gp;
|
|
button->key = key;
|
|
|
|
button->button = gtk_button_new();
|
|
gtk_widget_set_size_request(button->button,
|
|
key->width, key->height);
|
|
gtk_widget_set(button->button, "can-focus", FALSE, NULL);
|
|
|
|
x49gp_ui_button_pixmaps_init(x49gp, button, key->color);
|
|
|
|
if (key->label) {
|
|
button->label = gtk_label_new("");
|
|
gtk_widget_set_style(button->label,
|
|
button->button->style);
|
|
gtk_container_add(GTK_CONTAINER(button->button),
|
|
button->label);
|
|
|
|
g_signal_connect(G_OBJECT(button->label),
|
|
"expose-event",
|
|
G_CALLBACK(x49gp_button_expose_event),
|
|
button);
|
|
|
|
g_signal_connect_after(G_OBJECT(button->label),
|
|
"realize",
|
|
G_CALLBACK(x49gp_button_realize),
|
|
button);
|
|
}
|
|
|
|
button->box = gtk_event_box_new();
|
|
gtk_event_box_set_visible_window(GTK_EVENT_BOX(button->box),
|
|
TRUE);
|
|
gtk_event_box_set_above_child(GTK_EVENT_BOX(button->box),
|
|
FALSE);
|
|
gtk_widget_shape_combine_mask(button->box,
|
|
ui->shapes[key->shape], 0, 0);
|
|
gtk_container_add(GTK_CONTAINER(button->box), button->button);
|
|
|
|
|
|
x49gp_ui_place_at(x49gp, GTK_FIXED(ui->fixed), button->box,
|
|
ui->kb_x_offset + key->x,
|
|
ui->kb_y_offset + key->y,
|
|
key->width, key->height);
|
|
|
|
g_signal_connect(G_OBJECT(button->button),
|
|
"button-press-event",
|
|
G_CALLBACK(x49gp_ui_button_press), button);
|
|
|
|
g_signal_connect(G_OBJECT(button->button),
|
|
"button-release-event",
|
|
G_CALLBACK(x49gp_ui_button_release), button);
|
|
|
|
g_signal_connect(G_OBJECT(button->button),
|
|
"leave-notify-event",
|
|
G_CALLBACK(x49gp_ui_button_leave), button);
|
|
|
|
gtk_widget_add_events(button->button,
|
|
GDK_BUTTON_PRESS_MASK |
|
|
GDK_BUTTON_RELEASE_MASK |
|
|
GDK_LEAVE_NOTIFY_MASK);
|
|
}
|
|
|
|
ui->menu = gtk_menu_new();
|
|
|
|
menu_mount_folder = gtk_menu_item_new_with_label("Mount SD folder ...");
|
|
gtk_menu_shell_append(GTK_MENU_SHELL(ui->menu), menu_mount_folder);
|
|
g_signal_connect(G_OBJECT(menu_mount_folder), "activate",
|
|
G_CALLBACK(x49gp_ui_mount_sd_folder), x49gp);
|
|
menu_mount_image = gtk_menu_item_new_with_label("Mount SD image ...");
|
|
gtk_menu_shell_append(GTK_MENU_SHELL(ui->menu), menu_mount_image);
|
|
g_signal_connect(G_OBJECT(menu_mount_image), "activate",
|
|
G_CALLBACK(x49gp_ui_mount_sd_image), x49gp);
|
|
menu_unmount = gtk_menu_item_new_with_label("Unmount SD");
|
|
gtk_menu_shell_append(GTK_MENU_SHELL(ui->menu), menu_unmount);
|
|
g_signal_connect_swapped(G_OBJECT(menu_unmount), "activate",
|
|
G_CALLBACK(s3c2410_sdi_unmount), x49gp);
|
|
ui->menu_unmount = menu_unmount;
|
|
|
|
if (x49gp->debug_port != 0) {
|
|
gtk_menu_shell_append(GTK_MENU_SHELL(ui->menu),
|
|
gtk_separator_menu_item_new());
|
|
menu_debug = gtk_menu_item_new_with_label("Start debugger");
|
|
gtk_menu_shell_append(GTK_MENU_SHELL(ui->menu), menu_debug);
|
|
g_signal_connect(G_OBJECT(menu_debug), "activate",
|
|
G_CALLBACK(x49gp_ui_debug), x49gp);
|
|
ui->menu_debug = menu_debug;
|
|
} else
|
|
ui->menu_debug = NULL;
|
|
|
|
gtk_menu_shell_append(GTK_MENU_SHELL(ui->menu),
|
|
gtk_separator_menu_item_new());
|
|
menu_reset = gtk_menu_item_new_with_label("Reset");
|
|
gtk_menu_shell_append(GTK_MENU_SHELL(ui->menu), menu_reset);
|
|
g_signal_connect(G_OBJECT(menu_reset), "activate",
|
|
G_CALLBACK(x49gp_ui_calculator_reset), x49gp);
|
|
menu_quit = gtk_menu_item_new_with_label("Quit");
|
|
gtk_menu_shell_append(GTK_MENU_SHELL(ui->menu), menu_quit);
|
|
g_signal_connect_swapped(G_OBJECT(menu_quit), "activate",
|
|
G_CALLBACK(x49gp_ui_quit), x49gp);
|
|
|
|
gtk_widget_show_all(ui->menu);
|
|
|
|
g_signal_connect(G_OBJECT(screen_box), "button-press-event",
|
|
G_CALLBACK(x49gp_ui_show_menu), x49gp);
|
|
|
|
g_signal_connect(G_OBJECT(ui->background), "configure-event",
|
|
G_CALLBACK(x49gp_window_configure_event), x49gp);
|
|
|
|
g_signal_connect(G_OBJECT(ui->lcd_canvas), "expose-event",
|
|
G_CALLBACK(x49gp_lcd_expose_event), x49gp);
|
|
g_signal_connect(G_OBJECT(ui->lcd_canvas), "configure-event",
|
|
G_CALLBACK(x49gp_lcd_configure_event), x49gp);
|
|
|
|
g_signal_connect_swapped(G_OBJECT(ui->window), "delete-event",
|
|
G_CALLBACK(x49gp_ui_quit), x49gp);
|
|
g_signal_connect_swapped(G_OBJECT(ui->window), "destroy",
|
|
G_CALLBACK(x49gp_ui_quit), x49gp);
|
|
|
|
g_signal_connect(G_OBJECT(ui->window), "focus-out-event",
|
|
G_CALLBACK(x49gp_ui_focus_lost), x49gp);
|
|
|
|
g_signal_connect(G_OBJECT(ui->window), "key-press-event",
|
|
G_CALLBACK(x49gp_ui_key_event), x49gp);
|
|
g_signal_connect(G_OBJECT(ui->window), "key-release-event",
|
|
G_CALLBACK(x49gp_ui_key_event), x49gp);
|
|
|
|
g_signal_connect(G_OBJECT(ui->window), "button-press-event",
|
|
G_CALLBACK(x49gp_window_button_press), x49gp);
|
|
|
|
gtk_widget_add_events(ui->window,
|
|
GDK_FOCUS_CHANGE_MASK |
|
|
GDK_BUTTON_PRESS_MASK |
|
|
GDK_KEY_PRESS_MASK |
|
|
GDK_KEY_RELEASE_MASK);
|
|
|
|
gtk_widget_show_all(ui->window);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
gui_save(x49gp_module_t *module, GKeyFile *keyfile)
|
|
{
|
|
x49gp_ui_t *ui = module->user_data;
|
|
|
|
x49gp_module_set_string(module, keyfile, "type",
|
|
ui->calculator == UI_CALCULATOR_HP49GP ?
|
|
"hp49g+" : "hp50g");
|
|
x49gp_module_set_string(module, keyfile, "name", ui->name);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
x49gp_ui_init(x49gp_t *x49gp)
|
|
{
|
|
x49gp_module_t *module;
|
|
|
|
if (x49gp_module_init(x49gp, "gui", gui_init, gui_exit,
|
|
gui_reset, gui_load, gui_save, NULL,
|
|
&module)) {
|
|
return -1;
|
|
}
|
|
|
|
return x49gp_module_register(module);
|
|
}
|