From: auroux
- Version 0.3.3
+ Version 0.4
@@ -127,6 +127,28 @@ the Tools menu):
is yellow) and thicknesses. Use the color and thickness toolbar buttons
to change these settings.
+ To insert a new text item, click at the location where the text is to be
+ inserted on the page, then type it in or paste it using the contextual
+ menu (note: no wrapping is performed). To modify a text item, click inside
+ it. The font and point size can be modified using the "Text Font" command
+ in the Tools menu (or the toolbar button). The color is the same as that
+ currently selected for the pen (and can be modified using the toolbar
+ buttons).
+
+ Text items can contain arbitrary Unicode characters, provided that a
+ suitable font is installed on your system. However, languages written
+ in a direction other than left-to-right might not be handled properly.
+ If a journal contains some items in a font that is unavailable on your
+ system, another one will be substituted. (Also, text items will be
+ lost if the document is opened in a version of Xournal prior to 0.4).
+ Finally, note that the printing and PDF export features only accept
+ TrueType and Type 1 scalable fonts (do not use any bitmap fonts), and
+ that the typesetting of the text may be slightly different in the
+ printout.
+
The ruler is not a tool by itself, but rather a special operating mode
@@ -136,15 +158,17 @@ the Tools menu):
- Each drawing tool (pen, eraser, highlighter) has a default setting
- (color, thickness, ...) associated to it.
- The "Default Pen", "Default Eraser", and "Default Highlighter" entries of
+ Each tool (pen, eraser, highlighter, text) has a default setting
+ (color, thickness, ... for the drawing tools, font and size for the
+ text tool) associated to it.
+ The "Default Pen", "Default Eraser", "Default Highlighter", and
+ "Default Text" entries of
the Tools menu select the appropriate tool and reset its settings to
the defaults. The toolbar also includes a "Default" button which
- resets the currently selected drawing tool to its default settings,
+ resets the currently selected tool to its default settings,
and a "Default Pen" button.
The text tool
+ The ruler
Default tools
The "Set As Default" entry of the Tools menu takes the current settings
- of the currently selected drawing tool and makes them the new default.
+ of the currently selected tool and makes them the new default.
@@ -471,7 +495,8 @@ file is much more compact than those produced via gnome-print, and
its pages have the same size as in Xournal. Highlighter strokes
are rendered in a partially transparent manner (note however that
applications such as xpdf and ghostview do not always handle
-PDF transparency properly).
+PDF transparency properly). Text items are rendered by embedding
+TrueType subsets or Type 1 fonts into the PDF document as appropriate.
Xournal also includes a PDF file parser compatible with PDF format @@ -495,7 +520,7 @@ configuration file include in particular:
+Version 0.4 (August 15, 2007): +
Version 0.3.3 (January 31, 2007):
Xournal stores its data in gzipped XML-like files. The gzipped data consists of a succession of XML tags describing the document. By convention, the -first few lines contain a header in the following format: +file header and trailer look like this:
<?xml version="1.0" standalone="no"?> +<xournal version="..."> <title>Xournal document - see http://math.mit.edu/~auroux/software/xournal/</title> -<xournal version="..."/> +... sequence of pages ... +</xournal>The <title> and <xournal> tags may only appear within the file header (not within the pages of the document). The version attribute of the <xournal> tag indicates which version of Xournal was used to create the document; it is currently ignored, but may be used in a later release if the file format changes in an incompatible manner. +(Following a suggestion of Matteo Abrate, starting with version 0.4 the +<xournal> tag is the document's root tag, and encloses all other tags).
The rest of the file is a sequence of pages, specified by a @@ -711,15 +752,15 @@ page of the PDF file. After the line specifying the background, the remainder of a <page> section is occupied by one or more layer sections
<layer> ... </layer>-describing the various strokes within a layer. Every page must +describing the various items within a layer. Every page must contain at least one layer; a layer may be empty. The successive layers are listed in their stacking order, from bottom to top.
-A layer consist of a collection of items, listed in the order in which +A layer consists of a collection of items, listed in the order in which they should be drawn (from bottom-most to top-most). -As of the current version, the only legal contents within a layer are +Up to version 0.3.3, the only legal contents within a layer are strokes. The format of a stroke is:
<stroke tool="..." color="..." width="..."> ... list of coordinates ... @@ -753,6 +794,25 @@ appropriate (otherwise the eraser tool will not interact properly with the stroke). The default precision used by Xournal for the x,y coordinates is 0.01 unit (1/7200 in). +Starting with version 0.4, layers also contain text items. +The format of a text item is: +
<text font="..." size="..." x="..." y="..." color="...">... text ...</text> ++The font attribute contains the font name, for example "Serif Bold +Italic"; if the font is not available, another font will be substituted. +The size attribute specifies the font size in points. The x +and y attributes specify the coordinates of the top-left corner +of the text box in page coordinates (measured in points from the top-left +corner of the page). Finally, the color attribute contains either +the name of a standard color or a hexadecimal RGBA value (see above). + ++The contents of the text are encoded in UTF-8, with the characters +'&', '<', '>' replaced by &, <, +>. Whitespace and linefeeds are preserved (in particular, +no extraneous whitespace should be inserted between the enclosing tags +and the text itself). +
Installation issues
diff --git a/pixmaps/xournal.svg b/pixmaps/xournal.svg new file mode 100644 index 0000000..11c3de6 --- /dev/null +++ b/pixmaps/xournal.svg @@ -0,0 +1,1177 @@ + + + diff --git a/src/TODO b/src/TODO index cabcc9a..bb8f696 100644 --- a/src/TODO +++ b/src/TODO @@ -1,14 +1,24 @@ List of features to be implemented (not in any particular order) ---------------------------------------------------------------- +- paste text directly into xournal, from xournal? + (instead of starting a text item and pasting into it) +- internationalization / translation of interface +- integration into desktop environment (document icons/previews? + mime type? click on xoj opens it? list app in start menu?) +- rewrite printing using GtkPrint + Cairo as GnomePrint replacement + (keep GnomePrint option for compatibility with GTK+ <2.10) +- xournal_page-shadow.diff (Martin Kiefel Feb 5 2007) +- "organizer" side panel (hierarchy of notes), cf. gjots - xoj2pdf on command line +- 'insert blank page after' command (more useful in PDF annot !) - load images as bg if given on command-line (as with PDF on commandline) - load PDF pages only on demand (create empty pixmaps at first if can parse PDF geometry ourselves, else try pdfinfo ??) -- de-map space key from button bar -- lasso selection tool + (and config option to limit total memory usage for PDF bitmaps) +- lasso selection tool (see shoffsta patch) + (http://shoffsta.afraid.org/Projects/Xournal/) - flatten (incl undo/redo...) - enabled only if nlayers>1 - resize selection -- text tool, font chooser, default font - color chooser (papercolor, pen color); maybe more default colors - printing: print-options, save printer settings (throughout a session, and on disk) (maybe a separate config file .xournal/gnome-print-settings) @@ -19,19 +29,36 @@ List of features to be implemented (not in any particular order) - more pen/highlighter shapes (chisel) - convert to/from Jarnal format; to/from MS Journal format??? - recalibration upon screen resize / compensation for miscalibration + (use ConfigureNotify event and XInput? cf "Bugs" tracker 08/2007) - find a better behavior for vertical space tool across page boundaries ? -- key mappings (pgup/dn for full page, up/dn for scroll) - (customize secondary mappings for tablet button use ?) + config options? 1) when there's not enough space at bottom of page: + - resize the page + - move stuff to next page + - move stuff to a new page + 2) when moving to another page: + - move everything + - move only what doesn't fit (??? looks hard) + option for vert space tool to also move the background?? + (PDF: cut-and-crop by running PDF code twice with 2 different clipboxes?) - copy/paste of an entire page (beware if PDF bg is not compatible!) - simple drawing tools: rectangles, ellipses - option to save all annotated files within the .xoj - non-antialiased version for handhelds - customize autogenerated save file names -- optimize speed in hand tool (process groups of motion events)? - (setting 1 pixel min threshold doesn't help -- look at GTK+ scrollbar code?) - layer dialog box to set visibility status of each layer regardless of which layer is being edited - display corruption on scroll down when bottom of window is obscured?? (probably a gnomecanvas or X bug -- expose event generated for wrong region, or not processed?) - bitmap preview for document icon in desktop environments? +- autosave at a regular interval in a given location +- keep only a few pages of a PDF file in memory at any given time; generate + pages by parsing pdf info rather than generating bitmaps for all of them. +- win32 port (Matteo Abrate) +- snap-to-grid tool? (Matteo Abrate) +- option to auto-save preferences on exit (Michele Codutti) +- EPOS 7/24/07: Thumbnails pane +- EPOS: Connect to EPOS api which sends A4 mapped points +- EPOS: Cut and Paste into OpenOffice applications and the GIMP (as bitmap??) +- EPOS: Export pages to pictures in the Jpg and Png formats. +- EPOS: Rotate Ink in custom angle. diff --git a/src/main.c b/src/main.c index 4ff98db..59afa6c 100644 --- a/src/main.c +++ b/src/main.c @@ -1,8 +1,3 @@ -#define ENABLE_XINPUT_BUGFIX 1 -/* change the above to 0 if you are experiencing calibration problems with - XInput and want to try things differently -*/ - #ifdef HAVE_CONFIG_H # include#endif @@ -33,17 +28,11 @@ void hide_unimplemented(void) gtk_widget_hide(GET_COMPONENT("filePrintOptions")); gtk_widget_hide(GET_COMPONENT("journalFlatten")); gtk_widget_hide(GET_COMPONENT("papercolorOther")); - gtk_widget_hide(GET_COMPONENT("toolsText")); - gtk_widget_hide(GET_COMPONENT("buttonText")); - gtk_widget_hide(GET_COMPONENT("button2Text")); - gtk_widget_hide(GET_COMPONENT("button3Text")); gtk_widget_hide(GET_COMPONENT("toolsSelectRegion")); gtk_widget_hide(GET_COMPONENT("buttonSelectRegion")); gtk_widget_hide(GET_COMPONENT("button2SelectRegion")); gtk_widget_hide(GET_COMPONENT("button3SelectRegion")); gtk_widget_hide(GET_COMPONENT("colorOther")); - gtk_widget_hide(GET_COMPONENT("toolsTextFont")); - gtk_widget_hide(GET_COMPONENT("toolsDefaultText")); gtk_widget_hide(GET_COMPONENT("helpIndex")); } @@ -71,6 +60,9 @@ void init_stuff (int argc, char *argv[]) // initialize preferences init_config_default(); load_config_from_file(); + ui.font_name = g_strdup(ui.default_font_name); + ui.font_size = ui.default_font_size; + ui.hiliter_alpha_mask = 0xffffff00 + (guint)(255*ui.hiliter_opacity); // we need an empty canvas prior to creating the journal structures canvas = GNOME_CANVAS (gnome_canvas_new_aa ()); @@ -107,7 +99,7 @@ void init_stuff (int argc, char *argv[]) b->tool_type = i; b->color_rgba = predef_colors_rgba[b->color_no]; if (i == TOOL_HIGHLIGHTER) { - b->color_rgba &= HILITER_ALPHA_MASK; + b->color_rgba &= ui.hiliter_alpha_mask; } b->thickness = predef_thickness[i][b->thickness_no]; } @@ -121,6 +113,7 @@ void init_stuff (int argc, char *argv[]) gtk_window_set_default_size(GTK_WINDOW (winMain), ui.window_default_width, ui.window_default_height); if (ui.maximize_at_start) gtk_window_maximize(GTK_WINDOW (winMain)); update_toolbar_and_menu(); + update_font_button(); gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(GET_COMPONENT("journalApplyAllPages")), ui.bg_apply_all_pages); @@ -132,6 +125,8 @@ void init_stuff (int argc, char *argv[]) gtk_window_fullscreen(GTK_WINDOW(winMain)); } + allow_all_accels(); + add_scroll_bindings(); // set up and initialize the canvas @@ -140,7 +135,6 @@ void init_stuff (int argc, char *argv[]) gtk_container_add (GTK_CONTAINER (w), GTK_WIDGET (canvas)); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (w), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_widget_set_events (GTK_WIDGET (canvas), GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); - gtk_widget_set_extension_events(GTK_WIDGET (canvas), GDK_EXTENSION_EVENTS_ALL); gnome_canvas_set_pixels_per_unit (canvas, ui.zoom); gnome_canvas_set_center_scroll_region (canvas, TRUE); gtk_layout_get_hadjustment(GTK_LAYOUT (canvas))->step_increment = ui.scrollbar_step_increment; @@ -182,7 +176,7 @@ void init_stuff (int argc, char *argv[]) device = (GdkDevice *)dev_list->data; if (device != gdk_device_get_core_pointer()) { /* get around a GDK bug: map the valuator range CORRECTLY to [0,1] */ -#if ENABLE_XINPUT_BUGFIX +#ifdef ENABLE_XINPUT_BUGFIX gdk_device_set_axis_use(device, 0, GDK_AXIS_IGNORE); gdk_device_set_axis_use(device, 1, GDK_AXIS_IGNORE); #endif @@ -195,6 +189,8 @@ void init_stuff (int argc, char *argv[]) gtk_widget_set_sensitive(GET_COMPONENT("optionsUseXInput"), FALSE); ui.use_xinput = ui.allow_xinput && can_xinput; + gtk_widget_set_extension_events(GTK_WIDGET (canvas), + ui.use_xinput?GDK_EXTENSION_EVENTS_ALL:GDK_EXTENSION_EVENTS_NONE); gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(GET_COMPONENT("optionsUseXInput")), ui.use_xinput); @@ -215,6 +211,7 @@ void init_stuff (int argc, char *argv[]) update_undo_redo_enabled(); update_copy_paste_enabled(); update_vbox_order(ui.vertical_order[ui.fullscreen?1:0]); + gtk_widget_grab_focus(GTK_WIDGET(canvas)); // show everything... diff --git a/src/sft.h b/src/sft.h new file mode 100644 index 0000000..bcb3d90 --- /dev/null +++ b/src/sft.h @@ -0,0 +1,678 @@ +/* modified from sft.h in libgnomeprint */ + +/* + * Copyright © 2002, 2003 Sun Microsystems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of Sun Microsystems, Inc. nor the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. + * SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES OR + * LIABILITIES SUFFERED BY LICENSEE AS A RESULT OF OR RELATING TO USE, + * MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR ITS DERIVATIVES. + * IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, + * PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE + * THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE + * SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +/* $Id$ */ + +/* @(#)sft.h 1.17 03/01/08 SMI */ + +/* + * @file sft.h + * @brief Sun Font Tools + * @author Alexander Gelfenbain + * @version 1.0 + */ + +/* + * Generated fonts contain an XUID entry in the form of: + * + * 103 0 T C1 N C2 C3 + * + * 103 - Sun's Adobe assigned XUID number. Contact person: Alexander Gelfenbain + * + * T - font type. 0: Type 3, 1: Type 42 + * C1 - CRC-32 of the entire source TrueType font + * N - number of glyphs in the subset + * C2 - CRC-32 of the array of glyph IDs used to generate the subset + * C3 - CRC-32 of the array of encoding numbers used to generate the subset + * + */ + + +#ifndef __SUBFONT_H +#define __SUBFONT_H + +#include +#include +#include + +#define false 0 /**< standard false value */ +#define true 1 /**< standard true value */ + +/* glib already deals with different compilers */ +#include + +/*@{*/ + typedef gint16 F2Dot14; /**< fixed: 2.14 */ + typedef gint32 F16Dot16; /**< fixed: 16.16 */ +/*@}*/ + + typedef struct { + guint16 s; + guint16 d; + } uint16pair; + +/** Return value of OpenTTFont() and CreateT3FromTTGlyphs() */ + enum SFErrCodes { + SF_OK, /**< no error */ + SF_BADFILE, /**< file not found */ + SF_FILEIO, /**< file I/O error */ + SF_MEMORY, /**< memory allocation error */ + SF_GLYPHNUM, /**< incorrect number of glyphs */ + SF_BADARG, /**< incorrect arguments */ + SF_TTFORMAT, /**< incorrect TrueType font format */ + SF_TABLEFORMAT, /**< incorrect format of a TrueType table */ + SF_FONTNO /**< incorrect logical font number of a TTC font */ + }; + +#ifndef FW_THIN /* WIN32 compilation would conflict */ +/** Value of the weight member of the TTGlobalFontInfo struct */ + enum WeightClass { + FW_THIN = 100, /**< Thin */ + FW_EXTRALIGHT = 200, /**< Extra-light (Ultra-light) */ + FW_LIGHT = 300, /**< Light */ + FW_NORMAL = 400, /**< Normal (Regular) */ + FW_MEDIUM = 500, /**< Medium */ + FW_SEMIBOLD = 600, /**< Semi-bold (Demi-bold) */ + FW_BOLD = 700, /**< Bold */ + FW_EXTRABOLD = 800, /**< Extra-bold (Ultra-bold) */ + FW_BLACK = 900 /**< Black (Heavy) */ + }; + +/** Value of the width member of the TTGlobalFontInfo struct */ + enum WidthClass { + FWIDTH_ULTRA_CONDENSED = 1, /**< 50% of normal */ + FWIDTH_EXTRA_CONDENSED = 2, /**< 62.5% of normal */ + FWIDTH_CONDENSED = 3, /**< 75% of normal */ + FWIDTH_SEMI_CONDENSED = 4, /**< 87.5% of normal */ + FWIDTH_NORMAL = 5, /**< Medium, 100% */ + FWIDTH_SEMI_EXPANDED = 6, /**< 112.5% of normal */ + FWIDTH_EXPANDED = 7, /**< 125% of normal */ + FWIDTH_EXTRA_EXPANDED = 8, /**< 150% of normal */ + FWIDTH_ULTRA_EXPANDED = 9 /**< 200% of normal */ + }; +#endif /* FW_THIN */ + +/** Type of the 'kern' table, stored in _TrueTypeFont::kerntype */ + enum KernType { + + KT_NONE = 0, /**< no kern table */ + KT_APPLE_NEW = 1, /**< new Apple kern table */ + KT_MICROSOFT = 2 /**< Microsoft table */ + }; + +/* Composite glyph flags definition */ + enum CompositeFlags { + ARG_1_AND_2_ARE_WORDS = 1, + ARGS_ARE_XY_VALUES = 1<<1, + ROUND_XY_TO_GRID = 1<<2, + WE_HAVE_A_SCALE = 1<<3, + MORE_COMPONENTS = 1<<5, + WE_HAVE_AN_X_AND_Y_SCALE = 1<<6, + WE_HAVE_A_TWO_BY_TWO = 1<<7, + WE_HAVE_INSTRUCTIONS = 1<<8, + USE_MY_METRICS = 1<<9, + OVERLAP_COMPOUND = 1<<10 + }; + +/** Flags for TrueType generation */ + enum TTCreationFlags { + TTCF_AutoName = 1, /**< Automatically generate a compact 'name' table. + If this flag is not set, name table is generated + either from an array of NameRecord structs passed as + arguments or if the array is NULL, 'name' table + of the generated TrueType file will be a copy + of the name table of the original file. + If this flag is set the array of NameRecord structs + is ignored and a very compact 'name' table is automatically + generated. */ + + TTCF_IncludeOS2 = 2 /** If this flag is set OS/2 table from the original font will be + copied to the subset */ + }; + + /** Structure used by GetTTGlyphMetrics() */ + /*- In horisontal writing mode right sidebearing is calculated using this formula + *- rsb = aw - (lsb + xMax - xMin) -*/ + typedef struct { + gint16 xMin; + gint16 yMin; + gint16 xMax; + gint16 yMax; + guint16 aw; /*- Advance Width (horisontal writing mode) */ + gint16 lsb; /*- Left sidebearing (horisontal writing mode) */ + guint16 ah; /*- advance height (vertical writing mode) */ + gint16 tsb; /*- top sidebearing (vertical writing mode) */ + } TTGlyphMetrics; + + + /** Structure used by GetTTSimpleGlyphMetrics() and GetTTSimpleCharMetrics() functions */ + typedef struct { + guint16 adv; /**< advance width or height */ + gint16 sb; /**< left or top sidebearing */ + } TTSimpleGlyphMetrics; + + /** Structure returned by ReadGlyphMetrics() */ + typedef struct { + guint16 aw, ah; + gint16 lsb, tsb; + } TTFullSimpleGlyphMetrics; + + +/** Structure used by the TrueType Creator and GetRawGlyphData() */ + + typedef struct { + guint32 glyphID; /**< glyph ID */ + guint16 nbytes; /**< number of bytes in glyph data */ + guint8 *ptr; /**< pointer to glyph data */ + guint16 aw; /**< advance width */ + gint16 lsb; /**< left sidebearing */ + guint16 compflag; /**< 0- if non-composite, 1- otherwise */ + guint16 npoints; /**< number of points */ + guint16 ncontours; /**< number of contours */ + /* */ + guint32 newID; /**< used internally by the TTCR */ + } GlyphData; + + + /* STSF defines NameRecord and FUnitBBox structures in its own include file sttypes.h */ + + typedef struct { + gint16 xMin; + gint16 yMin; + gint16 xMax; + gint16 yMax; + } FUnitBBox; + +/** Structure used by the TrueType Creator and CreateTTFromTTGlyphs() */ + typedef struct { + guint16 platformID; /**< Platform ID */ + guint16 encodingID; /**< Platform-specific encoding ID */ + guint16 languageID; /**< Language ID */ + guint16 nameID; /**< Name ID */ + guint16 slen; /**< String length in bytes */ + guint8 *sptr; /**< Pointer to string data (not zero-terminated!) */ + } NameRecord; + + +/** Return value of GetTTGlobalFontInfo() */ + + typedef struct { + char *family; /**< family name */ + guint16 *ufamily; /**< family name UCS2 */ + char *subfamily; /**< subfamily name */ + char *psname; /**< PostScript name */ + int weight; /**< value of WeightClass or 0 if can't be determined */ + int width; /**< value of WidthClass or 0 if can't be determined */ + int pitch; /**< 0: proportianal font, otherwise: monospaced */ + int italicAngle; /**< in counter-clockwise degrees * 65536 */ + guint16 fsSelection; /**< fsSelection field of OS/2 table */ + int xMin; /**< global bounding box: xMin */ + int yMin; /**< global bounding box: yMin */ + int xMax; /**< global bounding box: xMax */ + int yMax; /**< global bounding box: yMax */ + int ascender; /**< typographic ascent. */ + int descender; /**< typographic descent. */ + int linegap; /**< typographic line gap.\ Negative values are treated as + zero in Win 3.1, System 6 and System 7. */ + int vascent; /**< typographic ascent for vertical writing mode */ + int vdescent; /**< typographic descent for vertical writing mode */ + int typoAscender; /**< OS/2 portable typographic ascender */ + int typoDescender; /**< OS/2 portable typographic descender */ + int typoLineGap; /**< OS/2 portable typographc line gap */ + int winAscent; /**< ascender metric for Windows */ + int winDescent; /**< descender metric for Windows */ + int symbolEncoded; /**< 1: MS symbol encoded 0: not symbol encoded */ + int rangeFlag; /**< if set to 1 Unicode Range flags are applicable */ + guint32 ur1; /**< bits 0 - 31 of Unicode Range flags */ + guint32 ur2; /**< bits 32 - 63 of Unicode Range flags */ + guint32 ur3; /**< bits 64 - 95 of Unicode Range flags */ + guint32 ur4; /**< bits 96 - 127 of Unicode Range flags */ + guint8 panose[10]; /**< PANOSE classification number */ + guint16 typeFlags; /**< type flags (copyright information) */ + } TTGlobalFontInfo; + +/** Structure used by KernGlyphs() */ + typedef struct { + int x; /**< positive: right, negative: left */ + int y; /**< positive: up, negative: down */ + } KernData; + + +/** ControlPoint structure used by GetTTGlyphPoints() */ + typedef struct { + guint32 flags; /**< 00000000 00000000 e0000000 bbbbbbbb */ + /**< b - guint8 flags from the glyf array */ + /**< e == 0 - regular point */ + /**< e == 1 - end contour */ + gint16 x; /**< X coordinate in EmSquare units */ + gint16 y; /**< Y coordinate in EmSquare units */ + } ControlPoint; + + typedef struct _TrueTypeFont TrueTypeFont; + +/* + * @defgroup sft Sun Font Tools Exported Functions + */ + + +/* + * Get the number of fonts contained in a TrueType collection + * @param fname - file name + * @return number of fonts or zero, if file is not a TTC file. + * @ingroup sft + */ + int CountTTCFonts(const char* fname); + + +/* + * TrueTypeFont constructor. + * Reads the font file and allocates the memory for the structure. + * @param facenum - logical font number within a TTC file. This value is ignored + * for TrueType fonts + * @return value of SFErrCodes enum + * @ingroup sft + */ + int OpenTTFont(const char *fname, guint32 facenum, TrueTypeFont**); + +/* + * TrueTypeFont destructor. Deallocates the memory. + * @ingroup sft + */ + void CloseTTFont(TrueTypeFont *); + +/* + * Extracts TrueType control points, and stores them in an allocated array pointed to + * by *pointArray. This function returns the number of extracted points. + * + * @param ttf pointer to the TrueTypeFont structure + * @param glyphID Glyph ID + * @param pointArray Return value - address of the pointer to the first element of the array + * of points allocated by the function + * @return Returns the number of points in *pointArray or -1 if glyphID is + * invalid. + * @ingroup sft + * + */ +int GetTTGlyphPoints(TrueTypeFont *ttf, guint32 glyphID, ControlPoint **pointArray); + +/* + * Extracts bounding boxes in normalized FUnits (1000/em) for all glyphs in the + * font and allocates an array of FUnitBBox structures. There are ttf->nglyphs + * elements in the array. + * + * @param ttf pointer to the TrueTypeFont structure + * + * @return an array of FUnitBBox structures with values normalized to 1000 UPEm + * + * @ingroup sft + */ +FUnitBBox *GetTTGlyphBoundingBoxes(TrueTypeFont *ttf); + +/* + * Extracts raw glyph data from the 'glyf' table and returns it in an allocated + * GlyphData structure. + * + * @param ttf pointer to the TrueTypeFont structure + * @param glyphID Glyph ID + * + * @return pointer to an allocated GlyphData structure or NULL if + * glyphID is not present in the font + * @ingroup sft + * + */ + GlyphData *GetTTRawGlyphData(TrueTypeFont *ttf, guint32 glyphID); + +/* + * Extracts all Name Records from the font and stores them in an allocated + * array of NameRecord structs + * + * @param ttf pointer to the TrueTypeFont struct + * @param nr pointer to the array of NameRecord structs + * + * @return number of NameRecord structs + * @ingroup sft + */ + + int GetTTNameRecords(TrueTypeFont *ttf, NameRecord **nr); + +/* + * Deallocates previously allocated array of NameRecords. + * + * @param nr array of NameRecord structs + * @param n number of elements in the array + * + * @ingroup sft + */ + void DisposeNameRecords(NameRecord* nr, int n); + + +#ifndef NO_TYPE3 +/* + * Generates a new PostScript Type 3 font and dumps it to outf file. + * This functions subsititues glyph 0 for all glyphIDs that are not found in the font. + * @param ttf pointer to the TrueTypeFont structure + * @param outf the resulting font is written to this stream + * @param fname font name for the new font. If it is NULL the PostScript name of the + * original font will be used + * @param glyphArray pointer to an array of glyphs that are to be extracted from ttf + * @param encoding array of encoding values. encoding[i] specifies the position of the glyph + * glyphArray[i] in the encoding vector of the resulting Type3 font + * @param nGlyphs number of glyph IDs in glyphArray and encoding values in encoding + * @param wmode writing mode for the output file: 0 - horizontal, 1 - vertical + * @return return the value of SFErrCodes enum + * @see SFErrCodes + * @ingroup sft + * + */ + int CreateT3FromTTGlyphs(TrueTypeFont *ttf, FILE *outf, const char *fname, guint16 *glyphArray, guint8 *encoding, int nGlyphs, int wmode); +#endif + +#ifndef NO_TTCR +/* + * Generates a new TrueType font and dumps it to outf file. + * This functions subsititues glyph 0 for all glyphIDs that are not found in the font. + * @param ttf pointer to the TrueTypeFont structure + * @param fname file name for the output TrueType font file + * @param glyphArray pointer to an array of glyphs that are to be extracted from ttf. The first + * element of this array has to be glyph 0 (default glyph) + * @param encoding array of encoding values. encoding[i] specifies character code for + * the glyphID glyphArray[i]. Character code 0 usually points to a default + * glyph (glyphID 0) + * @param nGlyphs number of glyph IDs in glyphArray and encoding values in encoding + * @param nNameRecs number of NameRecords for the font, if 0 the name table from the + * original font will be used + * @param nr array of NameRecords + * @param flags or'ed TTCreationFlags + * @return return the value of SFErrCodes enum + * @see SFErrCodes + * @ingroup sft + * + */ + int CreateTTFromTTGlyphs(TrueTypeFont *ttf, + const char *fname, + guint16 *glyphArray, + guint8 *encoding, + int nGlyphs, + int nNameRecs, + NameRecord *nr, + guint32 flags); +#endif + +#ifndef NO_TYPE42 +/* + * Generates a new PostScript Type42 font and dumps it to outf file. + * This functions subsititues glyph 0 for all glyphIDs that are not found in the font. + * @param ttf pointer to the TrueTypeFont structure + * @param outf output stream for a resulting font + * @param psname PostScript name of the resulting font + * @param glyphArray pointer to an array of glyphs that are to be extracted from ttf. The first + * element of this array has to be glyph 0 (default glyph) + * @param encoding array of encoding values. encoding[i] specifies character code for + * the glyphID glyphArray[i]. Character code 0 usually points to a default + * glyph (glyphID 0) + * @param nGlyphs number of glyph IDs in glyphArray and encoding values in encoding + * @return SF_OK - no errors + * SF_GLYPHNUM - too many glyphs (> 255) + * SF_TTFORMAT - corrupted TrueType fonts + * + * @see SFErrCodes + * @ingroup sft + * + */ + int CreateT42FromTTGlyphs(TrueTypeFont *ttf, + FILE *outf, + const char *psname, + guint16 *glyphArray, + guint8 *encoding, + int nGlyphs); +#endif + +/* + * Queries full glyph metrics for one glyph + */ +void GetTTGlyphMetrics(TrueTypeFont *ttf, guint32 glyphID, TTGlyphMetrics *metrics); + + +/* + * Queries glyph metrics. Allocates an array of TTSimpleGlyphMetrics structs and returns it. + * + * @param ttf pointer to the TrueTypeFont structure + * @param glyphArray pointer to an array of glyphs that are to be extracted from ttf + * @param nGlyphs number of glyph IDs in glyphArray and encoding values in encoding + * @param mode writing mode: 0 - horizontal, 1 - vertical + * @ingroup sft + * + */ +TTSimpleGlyphMetrics *GetTTSimpleGlyphMetrics(TrueTypeFont *ttf, guint16 *glyphArray, int nGlyphs, int mode); + +#ifndef NO_MAPPERS +/* + * Queries character metrics. Allocates an array of TTSimpleGlyphMetrics structs and returns it. + * This function behaves just like GetTTSimpleGlyphMetrics() but it takes a range of Unicode + * characters instead of an array of glyphs. + * + * @param ttf pointer to the TrueTypeFont structure + * @param firstChar Unicode value of the first character in the range + * @param nChars number of Unicode characters in the range + * @param mode writing mode: 0 - horizontal, 1 - vertical + * + * @see GetTTSimpleGlyphMetrics + * @ingroup sft + * + */ + TTSimpleGlyphMetrics *GetTTSimpleCharMetrics(TrueTypeFont *ttf, guint16 firstChar, int nChars, int mode); + +/* + * Maps a Unicode (UCS-2) string to a glyph array. Returns the number of glyphs in the array, + * which for TrueType fonts is always the same as the number of input characters. + * + * @param ttf pointer to the TrueTypeFont structure + * @param str pointer to a UCS-2 string + * @param nchars number of characters in str + * @param glyphArray pointer to the glyph array where glyph IDs are to be recorded. + * + * @return MapString() returns -1 if the TrueType font has no usable 'cmap' tables. + * Otherwise it returns the number of characters processed: nChars + * + * glyphIDs of TrueType fonts are 2 guint8 positive numbers. glyphID of 0 denotes a missing + * glyph and traditionally defaults to an empty square. + * glyphArray should be at least sizeof(guint16) * nchars bytes long. If glyphArray is NULL + * MapString() replaces the UCS-2 characters in str with glyphIDs. + * @ingroup sft + */ +#ifdef USE_GSUB + int MapString(TrueTypeFont *ttf, guint16 *str, int nchars, guint16 *glyphArray, int bvertical); +#else + int MapString(TrueTypeFont *ttf, guint16 *str, int nchars, guint16 *glyphArray); +#endif + +/* + * Maps a Unicode (UCS-2) character to a glyph ID and returns it. Missing glyph has + * a glyphID of 0 so this function can be used to test if a character is encoded in the font. + * + * @param ttf pointer to the TrueTypeFont structure + * @param ch Unicode (UCS-2) character + * @return glyph ID, if the character is missing in the font, the return value is 0. + * @ingroup sft + */ +#ifdef USE_GSUB + guint16 MapChar(TrueTypeFont *ttf, guint16 ch, int bvertical); +#else + guint16 MapChar(TrueTypeFont *ttf, guint16 ch); +#endif +#endif + +/* + * Returns global font information about the TrueType font. + * @see TTGlobalFontInfo + * + * @param ttf pointer to a TrueTypeFont structure + * @param info pointer to a TTGlobalFontInfo structure + * @ingroup sft + * + */ + void GetTTGlobalFontInfo(TrueTypeFont *ttf, TTGlobalFontInfo *info); + +/* + * Returns kerning information for an array of glyphs. + * Kerning is not cumulative. + * kern[i] contains kerning information for a pair of glyphs at positions i and i+1 + * + * @param ttf pointer to a TrueTypeFont structure + * @param glyphs array of source glyphs + * @param nglyphs number of glyphs in the array + * @param wmode writing mode: 0 - horizontal, 1 - vertical + * @param kern array of KernData structures. It should contain nglyphs-1 elements + * @see KernData + * @ingroup sft + * + */ +void KernGlyphs(TrueTypeFont *ttf, guint16 *glyphs, int nglyphs, int wmode, KernData *kern); + +/* + * Returns nonzero if font is a symbol encoded font + */ +int CheckSymbolEncoding(TrueTypeFont* ttf); + +/* + * Extracts a 'cmap' table from a font, allocates memory for it and returns a pointer to it. + * DEPRECATED - use ExtractTable instead + */ +#if 0 +guint8 *ExtractCmap(TrueTypeFont *ttf); +#endif + +/* + * Extracts a table from a font, allocates memort for it and returns a pointer to it. + */ +guint8 *ExtractTable(TrueTypeFont *ttf, guint32 tag); + +/* + * Returns a pointer to the table but does not allocate memory for it. + */ +const guint8 *GetTable(TrueTypeFont *ttf, guint32 tag); + +/* + * Functions that do not use TrueTypeFont structure + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +/* + * Reads full (vertical and horisontal) glyph metrics for an array of glyphs from hmtx and vmtx tables + * + * @param hmtx TrueType hmtx table + * @param vmtx TrueType vmtx table + * @param hcount numberOfHMetrics value + * @param vcount numOfLongVerMetrics value + * @param gcount total number of glyphs in the font + * @param UPEm units per Em value + * @param glyphArray array of source glyph IDs + * @param nGlyphs number of glyphs in the glyphArray array + * + * @return array of TTFullSimpleGlyphMetrics data structures + * + */ + +TTFullSimpleGlyphMetrics *ReadGlyphMetrics(guint8 *hmtx, guint8 *vmtx, int hcount, int vcount, int gcount, int UPEm, guint16 *glyphArray, int nGlyphs); + +void ReadSingleGlyphMetrics(guint8 *hmtx, guint8 *vmtx, int hcount, int vcount, int gcount, int UPEm, guint16 glyphID, TTFullSimpleGlyphMetrics *metrics); + + +/* + * Returns the length of the 'kern' subtable + * + * @param kern pointer to the 'kern' subtable + * + * @return number of bytes in it + */ +guint32 GetKernSubtableLength(guint8 *kern); + +/* + * Kerns a pair of glyphs. + * + * @param kerntype type of the kern table + * @param nkern number of kern subtables + * @param kern array of pointers to kern subtables + * @pram unitsPerEm units per Em value + * @param wmode writing mode: 0 - horizontal, 1 - vertical + * @param a ID of the first glyoh + * @param b ID of the second glyoh + * @param x X-axis kerning value is returned here + * @param y Y-axis kerning value is returned here + */ +void KernGlyphPair(int kerntype, guint32 nkern, guint8 **kern, int unitsPerEm, int wmode, guint32 a, guint32 b, int *x, int *y); + + + +/*- private definitions */ /*FOLD00*/ + +struct _TrueTypeFont { + guint32 tag; + + char *fname; + off_t fsize; + guint8 *ptr; + + char *psname; + char *family; + guint16 *ufamily; + char *subfamily; + + guint32 ntables; + guint32 tdoffset; /* offset to the table directory (!= 0 for TrueType collections) */ + guint32 *goffsets; + int nglyphs; + int unitsPerEm; + int numberOfHMetrics; + int numOfLongVerMetrics; /* if this number is not 0, font has vertical metrics information */ + guint8 *cmap; + int cmapType; + guint16 (*mapper)(const guint8 *, guint16); /* character to glyphID translation function */ + void **tables; /* array of pointers to tables */ + guint32 *tlens; /* array of table lengths */ + int kerntype; /* Defined in the KernType enum */ + guint32 nkern; /* number of kern subtables */ + guint8 **kerntables; /* array of pointers to kern subtables */ +#ifdef USE_GSUB + void *pGSubstitution; /* info provided by GSUB for UseGSUB() */ +#endif +#if 0 + GnomePrintBuffer gp_buf; +#endif +}; + +#endif /* __SUBFONT_H */ diff --git a/src/xo-callbacks.c b/src/xo-callbacks.c index 038507a..2fa9d7c 100644 --- a/src/xo-callbacks.c +++ b/src/xo-callbacks.c @@ -23,6 +23,8 @@ void on_fileNew_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); if (close_journal()) { new_journal(); ui.zoom = ui.startup_zoom; @@ -43,6 +45,8 @@ on_fileNewBackground_activate (GtkMenuItem *menuitem, int file_domain; gboolean success; + end_text(); + reset_focus(); if (!ok_to_close()) return; // user aborted on save confirmation dialog = gtk_file_chooser_dialog_new("Open PDF", GTK_WINDOW (winMain), @@ -55,6 +59,7 @@ on_fileNewBackground_activate (GtkMenuItem *menuitem, filt_pdf = gtk_file_filter_new(); gtk_file_filter_set_name(filt_pdf, "PDF files"); gtk_file_filter_add_pattern(filt_pdf, "*.pdf"); + gtk_file_filter_add_pattern(filt_pdf, "*.PDF"); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_pdf); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all); @@ -111,6 +116,8 @@ on_fileOpen_activate (GtkMenuItem *menuitem, char *filename; gboolean success; + end_text(); + reset_focus(); if (!ok_to_close()) return; // user aborted on save confirmation dialog = gtk_file_chooser_dialog_new("Open Journal", GTK_WINDOW (winMain), @@ -156,6 +163,8 @@ on_fileSave_activate (GtkMenuItem *menuitem, { GtkWidget *dialog; + end_text(); + reset_focus(); if (ui.filename == NULL) { on_fileSaveAs_activate(menuitem, user_data); return; @@ -187,6 +196,8 @@ on_fileSaveAs_activate (GtkMenuItem *menuitem, gboolean warn; struct stat stat_buf; + end_text(); + reset_focus(); dialog = gtk_file_chooser_dialog_new("Save Journal", GTK_WINDOW (winMain), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL); @@ -287,6 +298,8 @@ on_filePrint_activate (GtkMenuItem *menuitem, guchar *s; GnomePrintConfig *config = gnome_print_config_default(); + end_text(); + reset_focus(); if (ui.filename!=NULL) { if (g_str_has_suffix(ui.filename, ".xoj")) { in_fn = g_strdup(ui.filename); @@ -369,6 +382,8 @@ on_filePrintPDF_activate (GtkMenuItem *menuitem, int response; gboolean warn; + end_text(); + reset_focus(); dialog = gtk_file_chooser_dialog_new("Export to PDF", GTK_WINDOW (winMain), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL); @@ -397,6 +412,7 @@ on_filePrintPDF_activate (GtkMenuItem *menuitem, filt_pdf = gtk_file_filter_new(); gtk_file_filter_set_name(filt_pdf, "PDF files"); gtk_file_filter_add_pattern(filt_pdf, "*.pdf"); + gtk_file_filter_add_pattern(filt_pdf, "*.PDF"); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_pdf); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all); gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); @@ -438,6 +454,8 @@ void on_fileQuit_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); if (ok_to_close()) gtk_main_quit (); } @@ -453,10 +471,13 @@ on_editUndo_activate (GtkMenuItem *menuitem, struct Brush tmp_brush; struct Background *tmp_bg; double tmp_x, tmp_y; + gchar *tmpstr; + end_text(); + reset_focus(); if (undo == NULL) return; // nothing to undo! reset_selection(); // safer - if (undo->type == ITEM_STROKE) { + if (undo->type == ITEM_STROKE || undo->type == ITEM_TEXT) { // we're keeping the stroke info, but deleting the canvas item gtk_object_destroy(GTK_OBJECT(undo->item->canvas_item)); undo->item->canvas_item = NULL; @@ -476,11 +497,8 @@ on_editUndo_activate (GtkMenuItem *menuitem, undo->layer->nitems--; } // recreate the deleted one - erasure->item->canvas_item = gnome_canvas_item_new(undo->layer->group, - gnome_canvas_line_get_type(), "points", erasure->item->path, - "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND, - "fill-color-rgba", erasure->item->brush.color_rgba, - "width-units", erasure->item->brush.thickness, NULL); + make_canvas_item_one(undo->layer->group, erasure->item); + undo->layer->items = g_list_insert(undo->layer->items, erasure->item, erasure->npos); if (erasure->npos == 0) @@ -592,16 +610,9 @@ on_editUndo_activate (GtkMenuItem *menuitem, (undo->val >= 0) ? undo->val:0); undo->page->nlayers++; - for (itemlist = undo->layer->items; itemlist!=NULL; itemlist = itemlist->next) { - it = (struct Item *)itemlist->data; - if (it->type == ITEM_STROKE) { - it->canvas_item = gnome_canvas_item_new(undo->layer->group, - gnome_canvas_line_get_type(), "points", it->path, - "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND, - "fill-color-rgba", it->brush.color_rgba, - "width-units", it->brush.thickness, NULL); - } - } + for (itemlist = undo->layer->items; itemlist!=NULL; itemlist = itemlist->next) + make_canvas_item_one(undo->layer->group, (struct Item *)itemlist->data); + do_switch_page(ui.pageno, FALSE, FALSE); // show the restored layer & others... } else if (undo->type == ITEM_REPAINTSEL) { @@ -615,8 +626,33 @@ on_editUndo_activate (GtkMenuItem *menuitem, gnome_canvas_item_set(it->canvas_item, "fill-color-rgba", it->brush.color_rgba, "width-units", it->brush.thickness, NULL); + if (it->type == ITEM_TEXT && it->canvas_item != NULL) + gnome_canvas_item_set(it->canvas_item, + "fill-color-rgba", it->brush.color_rgba, NULL); } } + else if (undo->type == ITEM_TEXT_EDIT) { + tmpstr = undo->str; + undo->str = undo->item->text; + undo->item->text = tmpstr; + gnome_canvas_item_set(undo->item->canvas_item, "text", tmpstr, NULL); + update_item_bbox(undo->item); + } + else if (undo->type == ITEM_TEXT_ATTRIB) { + tmpstr = undo->str; + undo->str = undo->item->font_name; + undo->item->font_name = tmpstr; + tmp_x = undo->val_x; + undo->val_x = undo->item->font_size; + undo->item->font_size = tmp_x; + g_memmove(&tmp_brush, undo->brush, sizeof(struct Brush)); + g_memmove(undo->brush, &(undo->item->brush), sizeof(struct Brush)); + g_memmove(&(undo->item->brush), &tmp_brush, sizeof(struct Brush)); + gnome_canvas_item_set(undo->item->canvas_item, + "fill-color-rgba", undo->item->brush.color_rgba, NULL); + update_text_item_displayfont(undo->item); + update_item_bbox(undo->item); + } // move item from undo to redo stack u = undo; @@ -641,16 +677,15 @@ on_editRedo_activate (GtkMenuItem *menuitem, struct Background *tmp_bg; struct Layer *l; double tmp_x, tmp_y; + gchar *tmpstr; + end_text(); + reset_focus(); if (redo == NULL) return; // nothing to redo! reset_selection(); // safer - if (redo->type == ITEM_STROKE) { + if (redo->type == ITEM_STROKE || redo->type == ITEM_TEXT) { // re-create the canvas_item - redo->item->canvas_item = gnome_canvas_item_new(redo->layer->group, - gnome_canvas_line_get_type(), "points", redo->item->path, - "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND, - "fill-color-rgba", redo->item->brush.color_rgba, - "width-units", redo->item->brush.thickness, NULL); + make_canvas_item_one(redo->layer->group, redo->item); // reinsert the item on its layer redo->layer->items = g_list_append(redo->layer->items, redo->item); redo->layer->nitems++; @@ -662,11 +697,7 @@ on_editRedo_activate (GtkMenuItem *menuitem, // re-create all the created items for (itemlist = erasure->replacement_items; itemlist!=NULL; itemlist = itemlist->next) { it = (struct Item *)itemlist->data; - it->canvas_item = gnome_canvas_item_new(redo->layer->group, - gnome_canvas_line_get_type(), "points", it->path, - "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND, - "fill-color-rgba", it->brush.color_rgba, - "width-units", it->brush.thickness, NULL); + make_canvas_item_one(redo->layer->group, it); redo->layer->items = g_list_insert_before(redo->layer->items, target, it); redo->layer->nitems++; lower_canvas_item_to(redo->layer->group, it->canvas_item, erasure->item->canvas_item); @@ -759,11 +790,7 @@ on_editRedo_activate (GtkMenuItem *menuitem, else if (redo->type == ITEM_PASTE) { for (itemlist = redo->itemlist; itemlist != NULL; itemlist = itemlist->next) { it = (struct Item *)itemlist->data; - it->canvas_item = gnome_canvas_item_new(redo->layer->group, - gnome_canvas_line_get_type(), "points", it->path, - "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND, - "fill-color-rgba", it->brush.color_rgba, - "width-units", it->brush.thickness, NULL); + make_canvas_item_one(redo->layer->group, it); redo->layer->items = g_list_append(redo->layer->items, it); redo->layer->nitems++; } @@ -805,8 +832,33 @@ on_editRedo_activate (GtkMenuItem *menuitem, gnome_canvas_item_set(it->canvas_item, "fill-color-rgba", it->brush.color_rgba, "width-units", it->brush.thickness, NULL); + if (it->type == ITEM_TEXT && it->canvas_item != NULL) + gnome_canvas_item_set(it->canvas_item, + "fill-color-rgba", it->brush.color_rgba, NULL); } } + else if (redo->type == ITEM_TEXT_EDIT) { + tmpstr = redo->str; + redo->str = redo->item->text; + redo->item->text = tmpstr; + gnome_canvas_item_set(redo->item->canvas_item, "text", tmpstr, NULL); + update_item_bbox(redo->item); + } + else if (redo->type == ITEM_TEXT_ATTRIB) { + tmpstr = redo->str; + redo->str = redo->item->font_name; + redo->item->font_name = tmpstr; + tmp_x = redo->val_x; + redo->val_x = redo->item->font_size; + redo->item->font_size = tmp_x; + g_memmove(&tmp_brush, redo->brush, sizeof(struct Brush)); + g_memmove(redo->brush, &(redo->item->brush), sizeof(struct Brush)); + g_memmove(&(redo->item->brush), &tmp_brush, sizeof(struct Brush)); + gnome_canvas_item_set(redo->item->canvas_item, + "fill-color-rgba", redo->item->brush.color_rgba, NULL); + update_text_item_displayfont(redo->item); + update_item_bbox(redo->item); + } // move item from redo to undo stack u = redo; @@ -823,6 +875,8 @@ void on_editCut_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); selection_to_clip(); selection_delete(); } @@ -832,6 +886,8 @@ void on_editCopy_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); selection_to_clip(); } @@ -840,6 +896,8 @@ void on_editPaste_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); clipboard_paste(); } @@ -848,6 +906,8 @@ void on_editDelete_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); selection_delete(); } @@ -860,6 +920,7 @@ on_viewContinuous_activate (GtkMenuItem *menuitem, double yscroll; struct Page *pg; + reset_focus(); if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return; if (ui.view_continuous) return; ui.view_continuous = TRUE; @@ -880,6 +941,7 @@ on_viewOnePage_activate (GtkMenuItem *menuitem, GtkAdjustment *v_adj; double yscroll; + reset_focus(); if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return; if (!ui.view_continuous) return; ui.view_continuous = FALSE; @@ -896,9 +958,11 @@ void on_viewZoomIn_activate (GtkMenuItem *menuitem, gpointer user_data) { + reset_focus(); if (ui.zoom > MAX_ZOOM) return; ui.zoom *= ui.zoom_step_factor; gnome_canvas_set_pixels_per_unit(canvas, ui.zoom); + rescale_text_items(); rescale_bg_pixmaps(); } @@ -907,9 +971,11 @@ void on_viewZoomOut_activate (GtkMenuItem *menuitem, gpointer user_data) { + reset_focus(); if (ui.zoom < MIN_ZOOM) return; ui.zoom /= ui.zoom_step_factor; gnome_canvas_set_pixels_per_unit(canvas, ui.zoom); + rescale_text_items(); rescale_bg_pixmaps(); } @@ -918,8 +984,10 @@ void on_viewNormalSize_activate (GtkMenuItem *menuitem, gpointer user_data) { + reset_focus(); ui.zoom = DEFAULT_ZOOM; gnome_canvas_set_pixels_per_unit(canvas, ui.zoom); + rescale_text_items(); rescale_bg_pixmaps(); } @@ -928,8 +996,10 @@ void on_viewPageWidth_activate (GtkMenuItem *menuitem, gpointer user_data) { + reset_focus(); ui.zoom = (GTK_WIDGET(canvas))->allocation.width/ui.cur_page->width; gnome_canvas_set_pixels_per_unit(canvas, ui.zoom); + rescale_text_items(); rescale_bg_pixmaps(); } @@ -938,6 +1008,8 @@ void on_viewFirstPage_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); do_switch_page(0, TRUE, FALSE); } @@ -946,6 +1018,8 @@ void on_viewPreviousPage_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); if (ui.pageno == 0) return; do_switch_page(ui.pageno-1, TRUE, FALSE); } @@ -955,6 +1029,8 @@ void on_viewNextPage_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); if (ui.pageno == journal.npages-1) { // create a page at end if (page_ops_forbidden()) return; on_journalNewPageEnd_activate(menuitem, user_data); @@ -968,6 +1044,8 @@ void on_viewLastPage_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); do_switch_page(journal.npages-1, TRUE, FALSE); } @@ -976,6 +1054,8 @@ void on_viewShowLayer_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); if (ui.layerno == ui.cur_page->nlayers-1) return; reset_selection(); ui.layerno++; @@ -989,6 +1069,8 @@ void on_viewHideLayer_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); if (ui.layerno == -1) return; reset_selection(); gnome_canvas_item_hide(GNOME_CANVAS_ITEM(ui.cur_layer->group)); @@ -1005,6 +1087,8 @@ on_journalNewPageBefore_activate (GtkMenuItem *menuitem, { struct Page *pg; + end_text(); + reset_focus(); if (page_ops_forbidden()) return; reset_selection(); pg = new_page(ui.cur_page); @@ -1025,6 +1109,8 @@ on_journalNewPageAfter_activate (GtkMenuItem *menuitem, { struct Page *pg; + end_text(); + reset_focus(); if (page_ops_forbidden()) return; reset_selection(); pg = new_page(ui.cur_page); @@ -1045,6 +1131,8 @@ on_journalNewPageEnd_activate (GtkMenuItem *menuitem, { struct Page *pg; + end_text(); + reset_focus(); if (page_ops_forbidden()) return; reset_selection(); pg = new_page((struct Page *)g_list_last(journal.pages)->data); @@ -1066,6 +1154,8 @@ on_journalDeletePage_activate (GtkMenuItem *menuitem, GList *layerlist, *itemlist; struct Layer *l; + end_text(); + reset_focus(); if (page_ops_forbidden()) return; if (journal.npages == 1) return; reset_selection(); @@ -1100,6 +1190,8 @@ on_journalNewLayer_activate (GtkMenuItem *menuitem, { struct Layer *l; + end_text(); + reset_focus(); reset_selection(); l = g_new(struct Layer, 1); l->items = NULL; @@ -1128,6 +1220,8 @@ on_journalDeleteLayer_activate (GtkMenuItem *menuitem, { GList *list; + end_text(); + reset_focus(); if (ui.cur_layer == NULL) return; reset_selection(); prepare_new_undo(); @@ -1199,6 +1293,8 @@ on_journalPaperSize_activate (GtkMenuItem *menuitem, struct Page *pg; GList *pglist; + end_text(); + reset_focus(); papersize_dialog = create_papersizeDialog(); papersize_width = ui.cur_page->width; papersize_height = ui.cur_page->height; @@ -1248,6 +1344,8 @@ void on_papercolorWhite_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); process_papercolor_activate(menuitem, COLOR_WHITE); } @@ -1256,6 +1354,8 @@ void on_papercolorYellow_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); process_papercolor_activate(menuitem, COLOR_YELLOW); } @@ -1264,6 +1364,8 @@ void on_papercolorPink_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); process_papercolor_activate(menuitem, COLOR_RED); } @@ -1272,6 +1374,8 @@ void on_papercolorOrange_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); process_papercolor_activate(menuitem, COLOR_ORANGE); } @@ -1280,6 +1384,8 @@ void on_papercolorBlue_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); process_papercolor_activate(menuitem, COLOR_BLUE); } @@ -1288,6 +1394,8 @@ void on_papercolorGreen_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); process_papercolor_activate(menuitem, COLOR_GREEN); } @@ -1304,6 +1412,8 @@ void on_paperstylePlain_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); process_paperstyle_activate(menuitem, RULING_NONE); } @@ -1312,6 +1422,8 @@ void on_paperstyleLined_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); process_paperstyle_activate(menuitem, RULING_LINED); } @@ -1320,6 +1432,8 @@ void on_paperstyleRuled_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); process_paperstyle_activate(menuitem, RULING_RULED); } @@ -1328,6 +1442,8 @@ void on_paperstyleGraph_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); process_paperstyle_activate(menuitem, RULING_GRAPH); } @@ -1345,6 +1461,8 @@ on_journalLoadBackground_activate (GtkMenuItem *menuitem, char *filename; gboolean attach; + end_text(); + reset_focus(); dialog = gtk_file_chooser_dialog_new("Open Background", GTK_WINDOW (winMain), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL); @@ -1368,7 +1486,9 @@ on_journalLoadBackground_activate (GtkMenuItem *menuitem, filt_pspdf = gtk_file_filter_new(); gtk_file_filter_set_name(filt_pspdf, "PS/PDF files (as bitmaps)"); gtk_file_filter_add_pattern(filt_pspdf, "*.ps"); + gtk_file_filter_add_pattern(filt_pspdf, "*.PS"); gtk_file_filter_add_pattern(filt_pspdf, "*.pdf"); + gtk_file_filter_add_pattern(filt_pspdf, "*.PDF"); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_pspdf); attach_opt = gtk_check_button_new_with_label("Attach file to the journal"); @@ -1444,6 +1564,7 @@ on_journalLoadBackground_activate (GtkMenuItem *menuitem, if (ui.zoom != DEFAULT_ZOOM) { ui.zoom = DEFAULT_ZOOM; gnome_canvas_set_pixels_per_unit(canvas, ui.zoom); + rescale_text_items(); rescale_bg_pixmaps(); } do_switch_page(ui.pageno, TRUE, TRUE); @@ -1455,6 +1576,8 @@ on_journalScreenshot_activate (GtkMenuItem *menuitem, { struct Background *bg; + end_text(); + reset_focus(); reset_selection(); gtk_window_iconify(GTK_WINDOW(winMain)); // hide ourselves gdk_display_sync(gdk_display_get_default()); @@ -1488,6 +1611,7 @@ on_journalScreenshot_activate (GtkMenuItem *menuitem, if (ui.zoom != DEFAULT_ZOOM) { ui.zoom = DEFAULT_ZOOM; gnome_canvas_set_pixels_per_unit(canvas, ui.zoom); + rescale_text_items(); rescale_bg_pixmaps(); } do_switch_page(ui.pageno, TRUE, TRUE); @@ -1500,6 +1624,8 @@ on_journalApplyAllPages_activate (GtkMenuItem *menuitem, { gboolean active; + end_text(); + reset_focus(); active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)); if (active == ui.bg_apply_all_pages) return; ui.bg_apply_all_pages = active; @@ -1551,6 +1677,8 @@ on_toolsPen_activate (GtkMenuItem *menuitem, if (ui.cur_mapping != 0) return; if (ui.toolno[0] == TOOL_PEN) return; + end_text(); + reset_focus(); reset_selection(); ui.toolno[0] = TOOL_PEN; ui.ruler[0] = FALSE; @@ -1578,6 +1706,8 @@ on_toolsEraser_activate (GtkMenuItem *menuitem, if (ui.cur_mapping != 0) return; if (ui.toolno[0] == TOOL_ERASER) return; + end_text(); + reset_focus(); reset_selection(); ui.toolno[0] = TOOL_ERASER; ui.ruler[0] = FALSE; @@ -1605,6 +1735,8 @@ on_toolsHighlighter_activate (GtkMenuItem *menuitem, if (ui.cur_mapping != 0) return; // not user-generated if (ui.toolno[0] == TOOL_HIGHLIGHTER) return; + end_text(); + reset_focus(); reset_selection(); ui.toolno[0] = TOOL_HIGHLIGHTER; ui.ruler[0] = FALSE; @@ -1621,7 +1753,27 @@ void on_toolsText_activate (GtkMenuItem *menuitem, gpointer user_data) { - + if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) { + if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) + return; + } else { + if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem))) + return; + } + + if (ui.cur_mapping != 0) return; // not user-generated + if (ui.toolno[0] == TOOL_TEXT) return; + + reset_focus(); + reset_selection(); + ui.toolno[0] = TOOL_TEXT; + ui.ruler[0] = FALSE; + ui.cur_brush = &(ui.brushes[0][TOOL_PEN]); + update_mapping_linkings(-1); + update_tool_buttons(); + update_tool_menu(); + update_color_menu(); + update_cursor(); } @@ -1648,6 +1800,8 @@ on_toolsSelectRectangle_activate (GtkMenuItem *menuitem, if (ui.cur_mapping != 0) return; // not user-generated if (ui.toolno[0] == TOOL_SELECTRECT) return; + end_text(); + reset_focus(); ui.toolno[0] = TOOL_SELECTRECT; ui.ruler[0] = FALSE; update_mapping_linkings(-1); @@ -1673,6 +1827,8 @@ on_toolsVerticalSpace_activate (GtkMenuItem *menuitem, if (ui.cur_mapping != 0) return; // not user-generated if (ui.toolno[0] == TOOL_VERTSPACE) return; + end_text(); + reset_focus(); reset_selection(); ui.toolno[0] = TOOL_VERTSPACE; ui.ruler[0] = FALSE; @@ -1850,6 +2006,8 @@ on_eraserStandard_activate (GtkMenuItem *menuitem, gpointer user_data) { if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return; + end_text(); + reset_focus(); ui.brushes[0][TOOL_ERASER].tool_options = TOOLOPT_ERASER_STANDARD; update_mapping_linkings(TOOL_ERASER); } @@ -1860,6 +2018,8 @@ on_eraserWhiteout_activate (GtkMenuItem *menuitem, gpointer user_data) { if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return; + end_text(); + reset_focus(); ui.brushes[0][TOOL_ERASER].tool_options = TOOLOPT_ERASER_WHITEOUT; update_mapping_linkings(TOOL_ERASER); } @@ -1870,6 +2030,8 @@ on_eraserDeleteStrokes_activate (GtkMenuItem *menuitem, gpointer user_data) { if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return; + end_text(); + reset_focus(); ui.brushes[0][TOOL_ERASER].tool_options = TOOLOPT_ERASER_STROKES; update_mapping_linkings(TOOL_ERASER); } @@ -1903,15 +2065,30 @@ void on_toolsTextFont_activate (GtkMenuItem *menuitem, gpointer user_data) { - -} - + GtkWidget *dialog; + gchar *str; + + dialog = gtk_font_selection_dialog_new("Select Font"); + str = make_cur_font_name(); + gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(dialog), str); + g_free(str); + if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) { + gtk_widget_destroy(dialog); + reset_focus(); + return; + } + str = gtk_font_selection_dialog_get_font_name(GTK_FONT_SELECTION_DIALOG(dialog)); + gtk_widget_destroy(dialog); + process_font_sel(str); +} void on_toolsDefaultPen_activate (GtkMenuItem *menuitem, gpointer user_data) { switch_mapping(0); + end_text(); + reset_focus(); reset_selection(); g_memmove(&(ui.brushes[0][TOOL_PEN]), ui.default_brushes+TOOL_PEN, sizeof(struct Brush)); ui.toolno[0] = TOOL_PEN; @@ -1931,6 +2108,8 @@ on_toolsDefaultEraser_activate (GtkMenuItem *menuitem, gpointer user_data) { switch_mapping(0); + end_text(); + reset_focus(); reset_selection(); g_memmove(&(ui.brushes[0][TOOL_ERASER]), ui.default_brushes+TOOL_ERASER, sizeof(struct Brush)); ui.toolno[0] = TOOL_ERASER; @@ -1950,6 +2129,8 @@ on_toolsDefaultHighlighter_activate (GtkMenuItem *menuitem, gpointer user_data) { switch_mapping(0); + end_text(); + reset_focus(); reset_selection(); g_memmove(&(ui.brushes[0][TOOL_HIGHLIGHTER]), ui.default_brushes+TOOL_HIGHLIGHTER, sizeof(struct Brush)); ui.toolno[0] = TOOL_HIGHLIGHTER; @@ -1967,7 +2148,27 @@ void on_toolsDefaultText_activate (GtkMenuItem *menuitem, gpointer user_data) { - + switch_mapping(0); + if (ui.toolno[0]!=TOOL_TEXT) end_text(); + reset_focus(); + reset_selection(); + ui.toolno[0] = TOOL_TEXT; + ui.ruler[0] = FALSE; + ui.cur_brush = &(ui.brushes[0][TOOL_PEN]); + ui.cur_brush->color_no = ui.default_brushes[TOOL_PEN].color_no; + ui.cur_brush->color_rgba = ui.default_brushes[TOOL_PEN].color_rgba; + g_free(ui.font_name); + ui.font_name = g_strdup(ui.default_font_name); + ui.font_size = ui.default_font_size; + if (ui.cur_item_type == ITEM_TEXT) { + refont_text_item(ui.cur_item, ui.font_name, ui.font_size); + } + update_font_button(); + update_mapping_linkings(-1); + update_tool_buttons(); + update_tool_menu(); + update_color_menu(); + update_cursor(); } @@ -1975,9 +2176,30 @@ void on_toolsSetAsDefault_activate (GtkMenuItem *menuitem, gpointer user_data) { + struct Item *it; + if (ui.cur_mapping!=0) return; if (ui.toolno[0] < NUM_STROKE_TOOLS) g_memmove(ui.default_brushes+ui.toolno[0], &(ui.brushes[0][ui.toolno[0]]), sizeof(struct Brush)); + if (ui.toolno[0] == TOOL_TEXT) { + if (ui.cur_item_type == ITEM_TEXT) { + g_free(ui.font_name); + ui.font_name = g_strdup(ui.cur_item->font_name); + ui.font_size = ui.cur_item->font_size; + } + else if (ui.selection!=NULL && ui.selection->items!=NULL && + ui.selection->items->next==NULL && + (it=(struct Item*)ui.selection->items->data)->type == ITEM_TEXT) { + g_free(ui.font_name); + ui.font_name = g_strdup(it->font_name); + ui.font_size = it->font_size; + } + g_free(ui.default_font_name); + ui.default_font_name = g_strdup(ui.font_name); + ui.default_font_size = ui.font_size; + } + end_text(); + reset_focus(); } @@ -1995,6 +2217,8 @@ on_toolsRuler_activate (GtkMenuItem *menuitem, if (ui.cur_mapping != 0) return; if (active == ui.ruler[0]) return; + end_text(); + reset_focus(); if (active && (ui.toolno[0]!=TOOL_PEN && ui.toolno[0]!=TOOL_HIGHLIGHTER)) { reset_selection(); ui.toolno[0] = TOOL_PEN; @@ -2015,6 +2239,8 @@ void on_optionsSavePreferences_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); save_config_to_file(); } @@ -2034,6 +2260,8 @@ on_helpAbout_activate (GtkMenuItem *menuitem, GtkWidget *aboutDialog; GtkLabel *labelTitle; + end_text(); + reset_focus(); aboutDialog = create_aboutDialog (); labelTitle = GTK_LABEL(g_object_get_data(G_OBJECT(aboutDialog), "labelTitle")); gtk_label_set_markup(labelTitle, @@ -2047,6 +2275,12 @@ void on_buttonToolDefault_clicked (GtkToolButton *toolbutton, gpointer user_data) { + if (ui.toolno[0]==TOOL_TEXT) { + on_toolsDefaultText_activate(NULL, NULL); + return; + } + end_text(); + reset_focus(); switch_mapping(0); if (ui.toolno[0] < NUM_STROKE_TOOLS) { g_memmove(&(ui.brushes[0][ui.toolno[0]]), ui.default_brushes+ui.toolno[0], sizeof(struct Brush)); @@ -2101,18 +2335,22 @@ on_canvas_button_press_event (GtkWidget *widget, GtkWidget *dialog; int mapping; gboolean is_core; - - if (ui.cur_item_type != ITEM_NONE) return FALSE; // we're already doing something - if (event->button > 3) return FALSE; // no painting with the mouse wheel! + struct Item *item; is_core = (event->device == gdk_device_get_core_pointer()); if (!ui.use_xinput && !is_core) return FALSE; if (ui.use_xinput && is_core && ui.discard_corepointer) return FALSE; + if (event->button > 3) return FALSE; // no painting with the mouse wheel! if (!is_core) { // re-get the axis values since Synaptics sends bogus ones gdk_device_get_state(event->device, event->window, event->axes, NULL); fix_xinput_coords((GdkEvent *)event); } + + if (ui.cur_item_type == ITEM_TEXT && !is_event_within_textview(event)) + end_text(); + if (ui.cur_item_type != ITEM_NONE) return FALSE; // we're already doing something + ui.is_corestroke = is_core; if (ui.use_erasertip && event->device->source == GDK_SOURCE_ERASER) @@ -2157,6 +2395,16 @@ on_canvas_button_press_event (GtkWidget *widget, ui.which_mouse_button = event->button; switch_mapping(mapping); + // in text tool, clicking in a text area edits it + if (ui.toolno[mapping] == TOOL_TEXT) { + item = click_is_in_text(ui.cur_layer, pt[0], pt[1]); + if (item!=NULL) { + reset_selection(); + start_text((GdkEvent *)event, item); + return FALSE; + } + } + // if this can be a selection move, then it takes precedence over anything else if (start_movesel((GdkEvent *)event)) return FALSE; @@ -2184,6 +2432,9 @@ on_canvas_button_press_event (GtkWidget *widget, else if (ui.toolno[mapping] == TOOL_VERTSPACE) { start_vertspace((GdkEvent *)event); } + else if (ui.toolno[mapping] == TOOL_TEXT) { + start_text((GdkEvent *)event, NULL); + } return FALSE; } @@ -2250,7 +2501,6 @@ on_canvas_key_press_event (GtkWidget *widget, GdkEventKey *event, gpointer user_data) { - return FALSE; } @@ -2321,7 +2571,8 @@ on_comboLayer_changed (GtkComboBox *combobox, if (ui.in_update_page_stuff) return; // avoid a bad retroaction - gtk_widget_grab_focus(GTK_WIDGET(canvas)); // stop focus on us + end_text(); + reset_focus(); val = gtk_combo_box_get_active(combobox); if (val == -1) return; @@ -2349,6 +2600,8 @@ on_winMain_delete_event (GtkWidget *widget, GdkEvent *event, gpointer user_data) { + end_text(); + reset_focus(); if (ok_to_close()) gtk_main_quit(); return TRUE; } @@ -2358,8 +2611,12 @@ void on_optionsUseXInput_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); ui.allow_xinput = ui.use_xinput = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)); + gtk_widget_set_extension_events(GTK_WIDGET (canvas), + ui.use_xinput?GDK_EXTENSION_EVENTS_ALL:GDK_EXTENSION_EVENTS_NONE); update_mappings_menu(); } @@ -2390,7 +2647,11 @@ on_vscroll_changed (GtkAdjustment *adjustment, ui.pageno--; tmppage = g_list_nth_data(journal.pages, ui.pageno); } - if (need_update) do_switch_page(ui.pageno, FALSE, FALSE); + if (need_update) { + end_text(); + do_switch_page(ui.pageno, FALSE, FALSE); + } + reset_focus(); return; } @@ -2401,8 +2662,9 @@ on_spinPageNo_value_changed (GtkSpinButton *spinbutton, int val; if (ui.in_update_page_stuff) return; // avoid a bad retroaction - - gtk_widget_grab_focus(GTK_WIDGET(canvas)); // stop blink-blink text cursor + + end_text(); + reset_focus(); val = gtk_spin_button_get_value_as_int(spinbutton) - 1; @@ -2426,6 +2688,8 @@ on_journalDefaultBackground_activate (GtkMenuItem *menuitem, struct Page *pg; GList *pglist; + end_text(); + reset_focus(); reset_selection(); pg = ui.cur_page; @@ -2461,6 +2725,8 @@ on_journalSetAsDefault_activate (GtkMenuItem *menuitem, { if (ui.cur_page->bg->type != BG_SOLID) return; + end_text(); + reset_focus(); prepare_new_undo(); undo->type = ITEM_NEW_DEFAULT_BG; undo->val_x = ui.default_page.width; @@ -2594,6 +2860,8 @@ on_viewFullscreen_activate (GtkMenuItem *menuitem, active = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)); if (active == ui.fullscreen) return; + end_text(); + reset_focus(); ui.fullscreen = active; gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(GET_COMPONENT("viewFullscreen")), ui.fullscreen); @@ -2611,6 +2879,8 @@ void on_optionsButtonMappings_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); ui.use_erasertip = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)); update_mappings_menu(); @@ -2625,6 +2895,8 @@ on_optionsAntialiasBG_activate (GtkMenuItem *menuitem, active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)); if (ui.antialias_bg == active) return; + end_text(); + reset_focus(); ui.antialias_bg = active; rescale_bg_pixmaps(); } @@ -2638,6 +2910,8 @@ on_optionsProgressiveBG_activate (GtkMenuItem *menuitem, active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)); if (ui.progressive_bg == active) return; + end_text(); + reset_focus(); ui.progressive_bg = active; if (!ui.progressive_bg) rescale_bg_pixmaps(); } @@ -2651,6 +2925,8 @@ on_mru_activate (GtkMenuItem *menuitem, gboolean success; GtkWidget *dialog; + end_text(); + reset_focus(); if (!ok_to_close()) return; // user aborted on save confirmation for (which = 0 ; which < MRU_SIZE; which++) { @@ -2700,7 +2976,7 @@ void on_button2Text_activate (GtkMenuItem *menuitem, gpointer user_data) { - + process_mapping_activate(menuitem, 1, TOOL_TEXT); } @@ -2735,6 +3011,8 @@ on_button2LinkBrush_activate (GtkMenuItem *menuitem, int i; if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return; + end_text(); + reset_focus(); ui.linked_brush[1] = BRUSH_LINKED; for (i=0;i = NUM_STROKE_TOOLS) { ui.linked_brush[1] = BRUSH_STATIC; update_mappings_menu_linkings(); @@ -2786,7 +3066,7 @@ void on_button3Text_activate (GtkMenuItem *menuitem, gpointer user_data) { - + process_mapping_activate(menuitem, 2, TOOL_TEXT); } @@ -2821,6 +3101,8 @@ on_button3LinkBrush_activate (GtkMenuItem *menuitem, int i; if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return; + end_text(); + reset_focus(); ui.linked_brush[2] = BRUSH_LINKED; for (i=0;i = NUM_STROKE_TOOLS) { ui.linked_brush[2] = BRUSH_STATIC; update_mappings_menu_linkings(); @@ -2856,6 +3140,8 @@ on_viewSetZoom_activate (GtkMenuItem *menuitem, double test_w, test_h; GtkSpinButton *spinZoom; + end_text(); + reset_focus(); zoom_dialog = create_zoomDialog(); zoom_percent = 100*ui.zoom / DEFAULT_ZOOM; spinZoom = GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(zoom_dialog), "spinZoom")); @@ -2881,6 +3167,7 @@ on_viewSetZoom_activate (GtkMenuItem *menuitem, if (response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY) { ui.zoom = DEFAULT_ZOOM*zoom_percent/100; gnome_canvas_set_pixels_per_unit(canvas, ui.zoom); + rescale_text_items(); rescale_bg_pixmaps(); } } while (response == GTK_RESPONSE_APPLY); @@ -2963,6 +3250,8 @@ on_toolsHand_activate (GtkMenuItem *menuitem, if (ui.cur_mapping != 0) return; if (ui.toolno[0] == TOOL_HAND) return; + end_text(); + reset_focus(); reset_selection(); ui.toolno[0] = TOOL_HAND; ui.ruler[0] = FALSE; @@ -2994,6 +3283,8 @@ void on_optionsPrintRuling_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); ui.print_ruling = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)); } @@ -3001,7 +3292,20 @@ void on_optionsDiscardCore_activate (GtkMenuItem *menuitem, gpointer user_data) { + end_text(); + reset_focus(); ui.discard_corepointer = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)); update_mappings_menu(); } + +void +on_fontButton_font_set (GtkFontButton *fontbutton, + gpointer user_data) +{ + gchar *str; + + str = g_strdup(gtk_font_button_get_font_name(fontbutton)); + process_font_sel(str); +} + diff --git a/src/xo-callbacks.h b/src/xo-callbacks.h index d7754cc..eb7b58f 100644 --- a/src/xo-callbacks.h +++ b/src/xo-callbacks.h @@ -600,3 +600,11 @@ on_optionsPrintRuling_activate (GtkMenuItem *menuitem, void on_optionsDiscardCore_activate (GtkMenuItem *menuitem, gpointer user_data); + +void +on_fontButton_font_set (GtkFontButton *fontbutton, + gpointer user_data); + +void +on_toggletoolClicked (GtkToolButton *toolbutton, + gpointer user_data); diff --git a/src/xo-file.c b/src/xo-file.c index ba2fad0..91044b0 100644 --- a/src/xo-file.c +++ b/src/xo-file.c @@ -21,8 +21,9 @@ #include "xo-callbacks.h" #include "xo-misc.h" #include "xo-file.h" +#include "xo-paint.h" -const char *tool_names[NUM_TOOLS] = {"pen", "eraser", "highlighter", "", "", "selectrect", "vertspace", "hand"}; +const char *tool_names[NUM_TOOLS] = {"pen", "eraser", "highlighter", "text", "", "selectrect", "vertspace", "hand"}; const char *color_names[COLOR_MAX] = {"black", "blue", "red", "green", "gray", "lightblue", "lightgreen", "magenta", "orange", "yellow", "white"}; const char *bgtype_names[3] = {"solid", "pixmap", "pdf"}; @@ -73,7 +74,7 @@ gboolean save_journal(const char *filename) struct Layer *layer; struct Item *item; int i, is_clone; - char *tmpfn; + char *tmpfn, *tmpstr; gchar *pdfbuf; gsize pdflen; gboolean success; @@ -88,8 +89,8 @@ gboolean save_journal(const char *filename) setlocale(LC_NUMERIC, "C"); gzprintf(f, "\n" - " Xournal document - see http://math.mit.edu/~auroux/software/xournal/ \n" - "\n"); + " \n" + " \n"); gzclose(f); setlocale(LC_NUMERIC, ""); @@ -471,9 +485,69 @@ void xoj_parser_start_element(GMarkupParseContext *context, tmpItem->brush.tool_options = 0; // who cares ? if (tmpItem->brush.tool_type == TOOL_HIGHLIGHTER) { if (tmpItem->brush.color_no >= 0) - tmpItem->brush.color_rgba &= HILITER_ALPHA_MASK; + tmpItem->brush.color_rgba &= ui.hiliter_alpha_mask; } } + else if (!strcmp(element_name, "text")) { // start of a text item + if (tmpLayer == NULL || tmpItem != NULL) { + *error = xoj_invalid(); + return; + } + tmpItem = (struct Item *)g_malloc0(sizeof(struct Item)); + tmpItem->type = ITEM_TEXT; + tmpItem->canvas_item = NULL; + tmpLayer->items = g_list_append(tmpLayer->items, tmpItem); + tmpLayer->nitems++; + // scan for font, size, x, y, and color attributes + has_attr = 0; + while (*attribute_names!=NULL) { + if (!strcmp(*attribute_names, "font")) { + if (has_attr & 1) *error = xoj_invalid(); + tmpItem->font_name = g_strdup(*attribute_values); + has_attr |= 1; + } + else if (!strcmp(*attribute_names, "size")) { + if (has_attr & 2) *error = xoj_invalid(); + cleanup_numeric((gchar *)*attribute_values); + tmpItem->font_size = g_ascii_strtod(*attribute_values, &ptr); + if (ptr == *attribute_values) *error = xoj_invalid(); + has_attr |= 2; + } + else if (!strcmp(*attribute_names, "x")) { + if (has_attr & 4) *error = xoj_invalid(); + cleanup_numeric((gchar *)*attribute_values); + tmpItem->bbox.left = g_ascii_strtod(*attribute_values, &ptr); + if (ptr == *attribute_values) *error = xoj_invalid(); + has_attr |= 4; + } + else if (!strcmp(*attribute_names, "y")) { + if (has_attr & 8) *error = xoj_invalid(); + cleanup_numeric((gchar *)*attribute_values); + tmpItem->bbox.top = g_ascii_strtod(*attribute_values, &ptr); + if (ptr == *attribute_values) *error = xoj_invalid(); + has_attr |= 8; + } + else if (!strcmp(*attribute_names, "color")) { + if (has_attr & 16) *error = xoj_invalid(); + tmpItem->brush.color_no = COLOR_OTHER; + for (i=0; iXournal document - see http://math.mit.edu/~auroux/software/xournal/ \n"); for (pagelist = journal.pages; pagelist!=NULL; pagelist = pagelist->next) { pg = (struct Page *)pagelist->data; gzprintf(f, "\n", pg->width, pg->height); @@ -178,11 +179,24 @@ gboolean save_journal(const char *filename) gzprintf(f, "%.2f ", item->path->coords[i]); gzprintf(f, "\n\n"); } + if (item->type == ITEM_TEXT) { + gzprintf(f, " \n"); } + gzprintf(f, "font_name, item->font_size, item->bbox.left, item->bbox.top); + if (item->brush.color_no >= 0) + gzputs(f, color_names[item->brush.color_no]); + else + gzprintf(f, "#%08x", item->brush.color_rgba); + tmpstr = g_markup_escape_text(item->text, -1); + gzprintf(f, "\">%s \n", tmpstr); + g_free(tmpstr); + + } } gzprintf(f, "\n"); } gzprintf(f, "brush.color_no = i; + tmpItem->brush.color_rgba = predef_colors_rgba[i]; + } + // there's also the case of hex (#rrggbbaa) colors + if (tmpItem->brush.color_no == COLOR_OTHER && **attribute_values == '#') { + tmpItem->brush.color_rgba = strtol(*attribute_values + 1, &ptr, 16); + if (*ptr!=0) *error = xoj_invalid(); + } + has_attr |= 16; + } + else *error = xoj_invalid(); + attribute_names++; + attribute_values++; + } + if (has_attr!=31) *error = xoj_invalid(); + } } void xoj_parser_end_element(GMarkupParseContext *context, @@ -502,6 +576,13 @@ void xoj_parser_end_element(GMarkupParseContext *context, update_item_bbox(tmpItem); tmpItem = NULL; } + if (!strcmp(element_name, "text")) { + if (tmpItem == NULL) { + *error = xoj_invalid(); + return; + } + tmpItem = NULL; + } } void xoj_parser_text(GMarkupParseContext *context, @@ -528,6 +609,11 @@ void xoj_parser_text(GMarkupParseContext *context, tmpItem->path = gnome_canvas_points_new(n/2); g_memmove(tmpItem->path->coords, ui.cur_path.coords, n*sizeof(double)); } + if (!strcmp(element_name, "text")) { + tmpItem->text = g_malloc(text_len+1); + g_memmove(tmpItem->text, text, text_len); + tmpItem->text[text_len]=0; + } } gboolean user_wants_second_chance(char **filename) @@ -711,8 +797,9 @@ GList *attempt_load_gv_bg(char *filename) char *pipename; int buflen, remnlen, file_pageno; - buf = g_malloc(BUFSIZE); // a reasonable buffer size f = fopen(filename, "r"); + if (f == NULL) return NULL; + buf = g_malloc(BUFSIZE); // a reasonable buffer size if (fread(buf, 1, 4, f) !=4 || (strncmp((char *)buf, "%!PS", 4) && strncmp((char *)buf, "%PDF", 4))) { fclose(f); @@ -1165,11 +1252,14 @@ void update_mru_menu(void) { int i; gboolean anyone = FALSE; + gchar *tmp; for (i=0; i ruling = RULING_LINED; ui.view_continuous = TRUE; ui.allow_xinput = TRUE; - ui.discard_corepointer = TRUE; + ui.discard_corepointer = FALSE; ui.bg_apply_all_pages = FALSE; ui.use_erasertip = FALSE; ui.window_default_width = 720; @@ -1246,6 +1336,8 @@ void init_config_default(void) ui.print_ruling = TRUE; ui.default_unit = UNIT_CM; ui.default_path = NULL; + ui.default_font_name = g_strdup(DEFAULT_FONT); + ui.default_font_size = DEFAULT_FONT_SIZE; // the default UI vertical order ui.vertical_order[0][0] = 1; @@ -1280,6 +1372,8 @@ void init_config_default(void) // predef_thickness is already initialized as a global variable GS_BITMAP_DPI = 144; PDFTOPPM_PRINTING_DPI = 150; + + ui.hiliter_opacity = 0.5; } #if GLIB_CHECK_VERSION(2,6,0) @@ -1376,6 +1470,9 @@ void save_config_to_file(void) update_keyval("general", "interface_fullscreen", " interface components in fullscreen mode, from top to bottom", verbose_vertical_order(ui.vertical_order[1])); + update_keyval("general", "highlighter_opacity", + " highlighter opacity (0 to 1, default 0.5)\n warning: opacity level is not saved in xoj files!", + g_strdup_printf("%.2f", ui.hiliter_opacity)); update_keyval("paper", "width", " the default page width, in points (1/72 in)", @@ -1436,7 +1533,7 @@ void save_config_to_file(void) " default highlighter thickness (fine = 1, medium = 2, thick = 3)", g_strdup_printf("%d", ui.default_brushes[TOOL_HIGHLIGHTER].thickness_no)); update_keyval("tools", "btn2_tool", - " button 2 tool (pen, eraser, highlighter, selectrect, vertspace, hand)", + " button 2 tool (pen, eraser, highlighter, text, selectrect, vertspace, hand)", g_strdup(tool_names[ui.toolno[1]])); update_keyval("tools", "btn2_linked", " button 2 brush linked to primary brush (true/false) (overrides all other settings)", @@ -1456,7 +1553,7 @@ void save_config_to_file(void) " button 2 eraser mode (eraser only)", g_strdup_printf("%d", ui.brushes[1][TOOL_ERASER].tool_options)); update_keyval("tools", "btn3_tool", - " button 3 tool (pen, eraser, highlighter, selectrect, vertspace, hand)", + " button 3 tool (pen, eraser, highlighter, text, selectrect, vertspace, hand)", g_strdup(tool_names[ui.toolno[2]])); update_keyval("tools", "btn3_linked", " button 3 brush linked to primary brush (true/false) (overrides all other settings)", @@ -1492,8 +1589,12 @@ void save_config_to_file(void) g_strdup_printf("%.2f;%.2f;%.2f", predef_thickness[TOOL_HIGHLIGHTER][1], predef_thickness[TOOL_HIGHLIGHTER][2], predef_thickness[TOOL_HIGHLIGHTER][3])); - // set comments for keys / groups that don't exist - // set keyvals to current options + update_keyval("tools", "default_font", + " name of the default font", + g_strdup(ui.default_font_name)); + update_keyval("tools", "default_font_size", + " default font size", + g_strdup_printf("%.1f", ui.default_font_size)); buf = g_key_file_to_data(ui.config_data, NULL, NULL); if (buf == NULL) return; @@ -1637,6 +1738,7 @@ void load_config_from_file(void) double f; gboolean b; int i, j; + gchar *str; #if GLIB_CHECK_VERSION(2,6,0) // no support for keyval files before Glib 2.6.0 @@ -1673,6 +1775,7 @@ void load_config_from_file(void) parse_keyval_string("general", "default_path", &ui.default_path); parse_keyval_vorderlist("general", "interface_order", ui.vertical_order[0]); parse_keyval_vorderlist("general", "interface_fullscreen", ui.vertical_order[1]); + parse_keyval_float("general", "highlighter_opacity", &ui.hiliter_opacity, 0., 1.); parse_keyval_float("paper", "width", &ui.default_page.width, 1., 5000.); parse_keyval_float("paper", "height", &ui.default_page.height, 1., 5000.); @@ -1735,5 +1838,8 @@ void load_config_from_file(void) parse_keyval_floatlist("tools", "pen_thicknesses", predef_thickness[TOOL_PEN], 5, 0.01, 1000.0); parse_keyval_floatlist("tools", "eraser_thicknesses", predef_thickness[TOOL_ERASER]+1, 3, 0.01, 1000.0); parse_keyval_floatlist("tools", "highlighter_thicknesses", predef_thickness[TOOL_HIGHLIGHTER]+1, 3, 0.01, 1000.0); + if (parse_keyval_string("tools", "default_font", &str)) + if (str!=NULL) { g_free(ui.default_font_name); ui.default_font_name = str; } + parse_keyval_float("tools", "default_font_size", &ui.default_font_size, 1., 200.); #endif } diff --git a/src/xo-interface.c b/src/xo-interface.c index 00114f5..1631189 100644 --- a/src/xo-interface.c +++ b/src/xo-interface.c @@ -317,6 +317,10 @@ create_winMain (void) GtkWidget *buttonYellow; GtkWidget *buttonWhite; GtkWidget *buttonColorOther; + GtkWidget *toolitem21; + GtkWidget *vseparator10; + GtkWidget *toolitem20; + GtkWidget *fontButton; GtkWidget *scrolledwindowMain; GtkWidget *hbox1; GtkWidget *labelPage; @@ -356,7 +360,7 @@ create_winMain (void) gtk_widget_show (fileNew); gtk_container_add (GTK_CONTAINER (menuFile_menu), fileNew); - fileNewBackground = gtk_image_menu_item_new_with_mnemonic ("Annotate PDF"); + fileNewBackground = gtk_image_menu_item_new_with_mnemonic ("Annotate PD_F"); gtk_widget_show (fileNewBackground); gtk_container_add (GTK_CONTAINER (menuFile_menu), fileNewBackground); @@ -381,7 +385,7 @@ create_winMain (void) gtk_container_add (GTK_CONTAINER (menuFile_menu), separator1); gtk_widget_set_sensitive (separator1, FALSE); - fileRecentFiles = gtk_menu_item_new_with_mnemonic ("Recent Files"); + fileRecentFiles = gtk_menu_item_new_with_mnemonic ("Recent Doc_uments"); gtk_widget_show (fileRecentFiles); gtk_container_add (GTK_CONTAINER (menuFile_menu), fileRecentFiles); @@ -436,10 +440,16 @@ create_winMain (void) filePrint = gtk_image_menu_item_new_from_stock ("gtk-print", accel_group); gtk_widget_show (filePrint); gtk_container_add (GTK_CONTAINER (menuFile_menu), filePrint); + gtk_widget_add_accelerator (filePrint, "activate", accel_group, + GDK_P, (GdkModifierType) GDK_CONTROL_MASK, + GTK_ACCEL_VISIBLE); - filePrintPDF = gtk_menu_item_new_with_mnemonic ("Export to PDF"); + filePrintPDF = gtk_menu_item_new_with_mnemonic ("_Export to PDF"); gtk_widget_show (filePrintPDF); gtk_container_add (GTK_CONTAINER (menuFile_menu), filePrintPDF); + gtk_widget_add_accelerator (filePrintPDF, "activate", accel_group, + GDK_E, (GdkModifierType) GDK_CONTROL_MASK, + GTK_ACCEL_VISIBLE); separator2 = gtk_separator_menu_item_new (); gtk_widget_show (separator2); @@ -460,10 +470,16 @@ create_winMain (void) editUndo = gtk_image_menu_item_new_from_stock ("gtk-undo", accel_group); gtk_widget_show (editUndo); gtk_container_add (GTK_CONTAINER (menuEdit_menu), editUndo); + gtk_widget_add_accelerator (editUndo, "activate", accel_group, + GDK_Z, (GdkModifierType) GDK_CONTROL_MASK, + GTK_ACCEL_VISIBLE); editRedo = gtk_image_menu_item_new_from_stock ("gtk-redo", accel_group); gtk_widget_show (editRedo); gtk_container_add (GTK_CONTAINER (menuEdit_menu), editRedo); + gtk_widget_add_accelerator (editRedo, "activate", accel_group, + GDK_Y, (GdkModifierType) GDK_CONTROL_MASK, + GTK_ACCEL_VISIBLE); separator3 = gtk_separator_menu_item_new (); gtk_widget_show (separator3); @@ -485,6 +501,9 @@ create_winMain (void) editDelete = gtk_image_menu_item_new_from_stock ("gtk-delete", accel_group); gtk_widget_show (editDelete); gtk_container_add (GTK_CONTAINER (menuEdit_menu), editDelete); + gtk_widget_add_accelerator (editDelete, "activate", accel_group, + GDK_Delete, (GdkModifierType) 0, + GTK_ACCEL_VISIBLE); menuView = gtk_menu_item_new_with_mnemonic ("_View"); gtk_widget_show (menuView); @@ -493,13 +512,13 @@ create_winMain (void) menuView_menu = gtk_menu_new (); gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuView), menuView_menu); - viewContinuous = gtk_radio_menu_item_new_with_mnemonic (viewContinuous_group, "Continuous"); + viewContinuous = gtk_radio_menu_item_new_with_mnemonic (viewContinuous_group, "_Continuous"); viewContinuous_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (viewContinuous)); gtk_widget_show (viewContinuous); gtk_container_add (GTK_CONTAINER (menuView_menu), viewContinuous); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (viewContinuous), TRUE); - viewOnePage = gtk_radio_menu_item_new_with_mnemonic (viewContinuous_group, "One Page"); + viewOnePage = gtk_radio_menu_item_new_with_mnemonic (viewContinuous_group, "_One Page"); viewContinuous_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (viewOnePage)); gtk_widget_show (viewOnePage); gtk_container_add (GTK_CONTAINER (menuView_menu), viewOnePage); @@ -513,6 +532,9 @@ create_winMain (void) viewFullscreen = gtk_check_menu_item_new_with_mnemonic ("Full Screen"); gtk_widget_show (viewFullscreen); gtk_container_add (GTK_CONTAINER (menuView_menu), viewFullscreen); + gtk_widget_add_accelerator (viewFullscreen, "activate", accel_group, + GDK_F11, (GdkModifierType) 0, + GTK_ACCEL_VISIBLE); separator4 = gtk_separator_menu_item_new (); gtk_widget_show (separator4); @@ -529,24 +551,36 @@ create_winMain (void) viewZoomIn = gtk_image_menu_item_new_from_stock ("gtk-zoom-in", accel_group); gtk_widget_show (viewZoomIn); gtk_container_add (GTK_CONTAINER (menuViewZoom_menu), viewZoomIn); + gtk_widget_add_accelerator (viewZoomIn, "activate", accel_group, + GDK_plus, (GdkModifierType) GDK_CONTROL_MASK, + GTK_ACCEL_VISIBLE); viewZoomOut = gtk_image_menu_item_new_from_stock ("gtk-zoom-out", accel_group); gtk_widget_show (viewZoomOut); gtk_container_add (GTK_CONTAINER (menuViewZoom_menu), viewZoomOut); + gtk_widget_add_accelerator (viewZoomOut, "activate", accel_group, + GDK_minus, (GdkModifierType) GDK_CONTROL_MASK, + GTK_ACCEL_VISIBLE); viewNormalSize = gtk_image_menu_item_new_from_stock ("gtk-zoom-100", accel_group); gtk_widget_show (viewNormalSize); gtk_container_add (GTK_CONTAINER (menuViewZoom_menu), viewNormalSize); + gtk_widget_add_accelerator (viewNormalSize, "activate", accel_group, + GDK_0, (GdkModifierType) GDK_CONTROL_MASK, + GTK_ACCEL_VISIBLE); - viewPageWidth = gtk_image_menu_item_new_with_mnemonic ("Page Width"); + viewPageWidth = gtk_image_menu_item_new_with_mnemonic ("Page _Width"); gtk_widget_show (viewPageWidth); gtk_container_add (GTK_CONTAINER (menuViewZoom_menu), viewPageWidth); + gtk_widget_add_accelerator (viewPageWidth, "activate", accel_group, + GDK_equal, (GdkModifierType) GDK_CONTROL_MASK, + GTK_ACCEL_VISIBLE); image625 = gtk_image_new_from_stock ("gtk-zoom-fit", GTK_ICON_SIZE_MENU); gtk_widget_show (image625); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (viewPageWidth), image625); - viewSetZoom = gtk_menu_item_new_with_mnemonic ("Set Zoom"); + viewSetZoom = gtk_menu_item_new_with_mnemonic ("_Set Zoom"); gtk_widget_show (viewSetZoom); gtk_container_add (GTK_CONTAINER (menuViewZoom_menu), viewSetZoom); @@ -555,33 +589,45 @@ create_winMain (void) gtk_container_add (GTK_CONTAINER (menuView_menu), separator5); gtk_widget_set_sensitive (separator5, FALSE); - viewFirstPage = gtk_image_menu_item_new_with_mnemonic ("First Page"); + viewFirstPage = gtk_image_menu_item_new_with_mnemonic ("_First Page"); gtk_widget_show (viewFirstPage); gtk_container_add (GTK_CONTAINER (menuView_menu), viewFirstPage); + gtk_widget_add_accelerator (viewFirstPage, "activate", accel_group, + GDK_Home, (GdkModifierType) GDK_CONTROL_MASK, + GTK_ACCEL_VISIBLE); image626 = gtk_image_new_from_stock ("gtk-goto-first", GTK_ICON_SIZE_MENU); gtk_widget_show (image626); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (viewFirstPage), image626); - viewPreviousPage = gtk_image_menu_item_new_with_mnemonic ("Previous Page"); + viewPreviousPage = gtk_image_menu_item_new_with_mnemonic ("_Previous Page"); gtk_widget_show (viewPreviousPage); gtk_container_add (GTK_CONTAINER (menuView_menu), viewPreviousPage); + gtk_widget_add_accelerator (viewPreviousPage, "activate", accel_group, + GDK_Left, (GdkModifierType) GDK_CONTROL_MASK, + GTK_ACCEL_VISIBLE); image627 = gtk_image_new_from_stock ("gtk-go-back", GTK_ICON_SIZE_MENU); gtk_widget_show (image627); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (viewPreviousPage), image627); - viewNextPage = gtk_image_menu_item_new_with_mnemonic ("Next Page"); + viewNextPage = gtk_image_menu_item_new_with_mnemonic ("_Next Page"); gtk_widget_show (viewNextPage); gtk_container_add (GTK_CONTAINER (menuView_menu), viewNextPage); + gtk_widget_add_accelerator (viewNextPage, "activate", accel_group, + GDK_Right, (GdkModifierType) GDK_CONTROL_MASK, + GTK_ACCEL_VISIBLE); image628 = gtk_image_new_from_stock ("gtk-go-forward", GTK_ICON_SIZE_MENU); gtk_widget_show (image628); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (viewNextPage), image628); - viewLastPage = gtk_image_menu_item_new_with_mnemonic ("Last Page"); + viewLastPage = gtk_image_menu_item_new_with_mnemonic ("_Last Page"); gtk_widget_show (viewLastPage); gtk_container_add (GTK_CONTAINER (menuView_menu), viewLastPage); + gtk_widget_add_accelerator (viewLastPage, "activate", accel_group, + GDK_End, (GdkModifierType) GDK_CONTROL_MASK, + GTK_ACCEL_VISIBLE); image629 = gtk_image_new_from_stock ("gtk-goto-last", GTK_ICON_SIZE_MENU); gtk_widget_show (image629); @@ -592,7 +638,7 @@ create_winMain (void) gtk_container_add (GTK_CONTAINER (menuView_menu), separator6); gtk_widget_set_sensitive (separator6, FALSE); - viewShowLayer = gtk_image_menu_item_new_with_mnemonic ("Show Layer"); + viewShowLayer = gtk_image_menu_item_new_with_mnemonic ("_Show Layer"); gtk_widget_show (viewShowLayer); gtk_container_add (GTK_CONTAINER (menuView_menu), viewShowLayer); @@ -600,7 +646,7 @@ create_winMain (void) gtk_widget_show (image630); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (viewShowLayer), image630); - viewHideLayer = gtk_image_menu_item_new_with_mnemonic ("Hide Layer"); + viewHideLayer = gtk_image_menu_item_new_with_mnemonic ("_Hide Layer"); gtk_widget_show (viewHideLayer); gtk_container_add (GTK_CONTAINER (menuView_menu), viewHideLayer); @@ -615,19 +661,19 @@ create_winMain (void) menuJournal_menu = gtk_menu_new (); gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuJournal), menuJournal_menu); - journalNewPageBefore = gtk_menu_item_new_with_mnemonic ("New Page Before"); + journalNewPageBefore = gtk_menu_item_new_with_mnemonic ("New Page _Before"); gtk_widget_show (journalNewPageBefore); gtk_container_add (GTK_CONTAINER (menuJournal_menu), journalNewPageBefore); - journalNewPageAfter = gtk_menu_item_new_with_mnemonic ("New Page After"); + journalNewPageAfter = gtk_menu_item_new_with_mnemonic ("New Page _After"); gtk_widget_show (journalNewPageAfter); gtk_container_add (GTK_CONTAINER (menuJournal_menu), journalNewPageAfter); - journalNewPageEnd = gtk_menu_item_new_with_mnemonic ("New Page At End"); + journalNewPageEnd = gtk_menu_item_new_with_mnemonic ("New Page At _End"); gtk_widget_show (journalNewPageEnd); gtk_container_add (GTK_CONTAINER (menuJournal_menu), journalNewPageEnd); - journalDeletePage = gtk_menu_item_new_with_mnemonic ("Delete Page"); + journalDeletePage = gtk_menu_item_new_with_mnemonic ("_Delete Page"); gtk_widget_show (journalDeletePage); gtk_container_add (GTK_CONTAINER (menuJournal_menu), journalDeletePage); @@ -636,15 +682,15 @@ create_winMain (void) gtk_container_add (GTK_CONTAINER (menuJournal_menu), separator7); gtk_widget_set_sensitive (separator7, FALSE); - journalNewLayer = gtk_menu_item_new_with_mnemonic ("New Layer"); + journalNewLayer = gtk_menu_item_new_with_mnemonic ("_New Layer"); gtk_widget_show (journalNewLayer); gtk_container_add (GTK_CONTAINER (menuJournal_menu), journalNewLayer); - journalDeleteLayer = gtk_menu_item_new_with_mnemonic ("Delete Layer"); + journalDeleteLayer = gtk_menu_item_new_with_mnemonic ("Delete La_yer"); gtk_widget_show (journalDeleteLayer); gtk_container_add (GTK_CONTAINER (menuJournal_menu), journalDeleteLayer); - journalFlatten = gtk_menu_item_new_with_mnemonic ("Flatten"); + journalFlatten = gtk_menu_item_new_with_mnemonic ("_Flatten"); gtk_widget_show (journalFlatten); gtk_container_add (GTK_CONTAINER (menuJournal_menu), journalFlatten); @@ -653,48 +699,48 @@ create_winMain (void) gtk_container_add (GTK_CONTAINER (menuJournal_menu), separator8); gtk_widget_set_sensitive (separator8, FALSE); - journalPaperSize = gtk_menu_item_new_with_mnemonic ("Paper Size"); + journalPaperSize = gtk_menu_item_new_with_mnemonic ("Paper Si_ze"); gtk_widget_show (journalPaperSize); gtk_container_add (GTK_CONTAINER (menuJournal_menu), journalPaperSize); - journalPaperColor = gtk_menu_item_new_with_mnemonic ("Paper Color"); + journalPaperColor = gtk_menu_item_new_with_mnemonic ("Paper _Color"); gtk_widget_show (journalPaperColor); gtk_container_add (GTK_CONTAINER (menuJournal_menu), journalPaperColor); journalPaperColor_menu = gtk_menu_new (); gtk_menu_item_set_submenu (GTK_MENU_ITEM (journalPaperColor), journalPaperColor_menu); - papercolorWhite = gtk_radio_menu_item_new_with_mnemonic (papercolorWhite_group, "white paper"); + papercolorWhite = gtk_radio_menu_item_new_with_mnemonic (papercolorWhite_group, "_white paper"); papercolorWhite_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (papercolorWhite)); gtk_widget_show (papercolorWhite); gtk_container_add (GTK_CONTAINER (journalPaperColor_menu), papercolorWhite); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (papercolorWhite), TRUE); - papercolorYellow = gtk_radio_menu_item_new_with_mnemonic (papercolorWhite_group, "yellow paper"); + papercolorYellow = gtk_radio_menu_item_new_with_mnemonic (papercolorWhite_group, "_yellow paper"); papercolorWhite_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (papercolorYellow)); gtk_widget_show (papercolorYellow); gtk_container_add (GTK_CONTAINER (journalPaperColor_menu), papercolorYellow); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (papercolorYellow), TRUE); - papercolorPink = gtk_radio_menu_item_new_with_mnemonic (papercolorWhite_group, "pink paper"); + papercolorPink = gtk_radio_menu_item_new_with_mnemonic (papercolorWhite_group, "_pink paper"); papercolorWhite_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (papercolorPink)); gtk_widget_show (papercolorPink); gtk_container_add (GTK_CONTAINER (journalPaperColor_menu), papercolorPink); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (papercolorPink), TRUE); - papercolorOrange = gtk_radio_menu_item_new_with_mnemonic (papercolorWhite_group, "orange paper"); + papercolorOrange = gtk_radio_menu_item_new_with_mnemonic (papercolorWhite_group, "_orange paper"); papercolorWhite_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (papercolorOrange)); gtk_widget_show (papercolorOrange); gtk_container_add (GTK_CONTAINER (journalPaperColor_menu), papercolorOrange); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (papercolorOrange), TRUE); - papercolorBlue = gtk_radio_menu_item_new_with_mnemonic (papercolorWhite_group, "blue paper"); + papercolorBlue = gtk_radio_menu_item_new_with_mnemonic (papercolorWhite_group, "_blue paper"); papercolorWhite_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (papercolorBlue)); gtk_widget_show (papercolorBlue); gtk_container_add (GTK_CONTAINER (journalPaperColor_menu), papercolorBlue); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (papercolorBlue), TRUE); - papercolorGreen = gtk_radio_menu_item_new_with_mnemonic (papercolorWhite_group, "green paper"); + papercolorGreen = gtk_radio_menu_item_new_with_mnemonic (papercolorWhite_group, "_green paper"); papercolorWhite_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (papercolorGreen)); gtk_widget_show (papercolorGreen); gtk_container_add (GTK_CONTAINER (journalPaperColor_menu), papercolorGreen); @@ -711,32 +757,32 @@ create_winMain (void) gtk_container_add (GTK_CONTAINER (journalPaperColor_menu), papercolorNA); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (papercolorNA), TRUE); - journalPaperStyle = gtk_menu_item_new_with_mnemonic ("Paper Style"); + journalPaperStyle = gtk_menu_item_new_with_mnemonic ("Paper _Style"); gtk_widget_show (journalPaperStyle); gtk_container_add (GTK_CONTAINER (menuJournal_menu), journalPaperStyle); journalPaperStyle_menu = gtk_menu_new (); gtk_menu_item_set_submenu (GTK_MENU_ITEM (journalPaperStyle), journalPaperStyle_menu); - paperstylePlain = gtk_radio_menu_item_new_with_mnemonic (paperstylePlain_group, "plain"); + paperstylePlain = gtk_radio_menu_item_new_with_mnemonic (paperstylePlain_group, "_plain"); paperstylePlain_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (paperstylePlain)); gtk_widget_show (paperstylePlain); gtk_container_add (GTK_CONTAINER (journalPaperStyle_menu), paperstylePlain); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (paperstylePlain), TRUE); - paperstyleLined = gtk_radio_menu_item_new_with_mnemonic (paperstylePlain_group, "lined"); + paperstyleLined = gtk_radio_menu_item_new_with_mnemonic (paperstylePlain_group, "_lined"); paperstylePlain_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (paperstyleLined)); gtk_widget_show (paperstyleLined); gtk_container_add (GTK_CONTAINER (journalPaperStyle_menu), paperstyleLined); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (paperstyleLined), TRUE); - paperstyleRuled = gtk_radio_menu_item_new_with_mnemonic (paperstylePlain_group, "ruled"); + paperstyleRuled = gtk_radio_menu_item_new_with_mnemonic (paperstylePlain_group, "_ruled"); paperstylePlain_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (paperstyleRuled)); gtk_widget_show (paperstyleRuled); gtk_container_add (GTK_CONTAINER (journalPaperStyle_menu), paperstyleRuled); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (paperstyleRuled), TRUE); - paperstyleGraph = gtk_radio_menu_item_new_with_mnemonic (paperstylePlain_group, "graph"); + paperstyleGraph = gtk_radio_menu_item_new_with_mnemonic (paperstylePlain_group, "_graph"); paperstylePlain_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (paperstyleGraph)); gtk_widget_show (paperstyleGraph); gtk_container_add (GTK_CONTAINER (journalPaperStyle_menu), paperstyleGraph); @@ -747,7 +793,7 @@ create_winMain (void) gtk_container_add (GTK_CONTAINER (journalPaperStyle_menu), paperstyleNA); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (paperstyleNA), TRUE); - journalApplyAllPages = gtk_check_menu_item_new_with_mnemonic ("Apply To All Pages"); + journalApplyAllPages = gtk_check_menu_item_new_with_mnemonic ("Apply _To All Pages"); gtk_widget_show (journalApplyAllPages); gtk_container_add (GTK_CONTAINER (menuJournal_menu), journalApplyAllPages); @@ -756,7 +802,7 @@ create_winMain (void) gtk_container_add (GTK_CONTAINER (menuJournal_menu), separator23); gtk_widget_set_sensitive (separator23, FALSE); - journalLoadBackground = gtk_image_menu_item_new_with_mnemonic ("Load Background"); + journalLoadBackground = gtk_image_menu_item_new_with_mnemonic ("_Load Background"); gtk_widget_show (journalLoadBackground); gtk_container_add (GTK_CONTAINER (menuJournal_menu), journalLoadBackground); @@ -764,7 +810,7 @@ create_winMain (void) gtk_widget_show (image632); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (journalLoadBackground), image632); - journalScreenshot = gtk_menu_item_new_with_mnemonic ("Background Screenshot"); + journalScreenshot = gtk_menu_item_new_with_mnemonic ("Background Screens_hot"); gtk_widget_show (journalScreenshot); gtk_container_add (GTK_CONTAINER (menuJournal_menu), journalScreenshot); @@ -773,11 +819,11 @@ create_winMain (void) gtk_container_add (GTK_CONTAINER (menuJournal_menu), separator19); gtk_widget_set_sensitive (separator19, FALSE); - journalDefaultBackground = gtk_menu_item_new_with_mnemonic ("Default Paper"); + journalDefaultBackground = gtk_menu_item_new_with_mnemonic ("Default _Paper"); gtk_widget_show (journalDefaultBackground); gtk_container_add (GTK_CONTAINER (menuJournal_menu), journalDefaultBackground); - journalSetAsDefault = gtk_menu_item_new_with_mnemonic ("Set As Default"); + journalSetAsDefault = gtk_menu_item_new_with_mnemonic ("Set As De_fault"); gtk_widget_show (journalSetAsDefault); gtk_container_add (GTK_CONTAINER (menuJournal_menu), journalSetAsDefault); @@ -792,24 +838,36 @@ create_winMain (void) toolsPen_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (toolsPen)); gtk_widget_show (toolsPen); gtk_container_add (GTK_CONTAINER (menuTools_menu), toolsPen); + gtk_widget_add_accelerator (toolsPen, "activate", accel_group, + GDK_P, (GdkModifierType) GDK_CONTROL_MASK | GDK_SHIFT_MASK, + GTK_ACCEL_VISIBLE); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (toolsPen), TRUE); toolsEraser = gtk_radio_menu_item_new_with_mnemonic (toolsPen_group, "_Eraser"); toolsPen_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (toolsEraser)); gtk_widget_show (toolsEraser); gtk_container_add (GTK_CONTAINER (menuTools_menu), toolsEraser); + gtk_widget_add_accelerator (toolsEraser, "activate", accel_group, + GDK_E, (GdkModifierType) GDK_CONTROL_MASK | GDK_SHIFT_MASK, + GTK_ACCEL_VISIBLE); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (toolsEraser), TRUE); toolsHighlighter = gtk_radio_menu_item_new_with_mnemonic (toolsPen_group, "_Highlighter"); toolsPen_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (toolsHighlighter)); gtk_widget_show (toolsHighlighter); gtk_container_add (GTK_CONTAINER (menuTools_menu), toolsHighlighter); + gtk_widget_add_accelerator (toolsHighlighter, "activate", accel_group, + GDK_H, (GdkModifierType) GDK_CONTROL_MASK | GDK_SHIFT_MASK, + GTK_ACCEL_VISIBLE); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (toolsHighlighter), TRUE); toolsText = gtk_radio_menu_item_new_with_mnemonic (toolsPen_group, "_Text"); toolsPen_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (toolsText)); gtk_widget_show (toolsText); gtk_container_add (GTK_CONTAINER (menuTools_menu), toolsText); + gtk_widget_add_accelerator (toolsText, "activate", accel_group, + GDK_T, (GdkModifierType) GDK_CONTROL_MASK | GDK_SHIFT_MASK, + GTK_ACCEL_VISIBLE); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (toolsText), TRUE); separator9 = gtk_separator_menu_item_new (); @@ -817,28 +875,40 @@ create_winMain (void) gtk_container_add (GTK_CONTAINER (menuTools_menu), separator9); gtk_widget_set_sensitive (separator9, FALSE); - toolsSelectRegion = gtk_radio_menu_item_new_with_mnemonic (toolsPen_group, "_Select Region"); + toolsSelectRegion = gtk_radio_menu_item_new_with_mnemonic (toolsPen_group, "Select Re_gion"); toolsPen_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (toolsSelectRegion)); gtk_widget_show (toolsSelectRegion); gtk_container_add (GTK_CONTAINER (menuTools_menu), toolsSelectRegion); + gtk_widget_add_accelerator (toolsSelectRegion, "activate", accel_group, + GDK_G, (GdkModifierType) GDK_CONTROL_MASK | GDK_SHIFT_MASK, + GTK_ACCEL_VISIBLE); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (toolsSelectRegion), TRUE); - toolsSelectRectangle = gtk_radio_menu_item_new_with_mnemonic (toolsPen_group, "Select Rectangle"); + toolsSelectRectangle = gtk_radio_menu_item_new_with_mnemonic (toolsPen_group, "Select _Rectangle"); toolsPen_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (toolsSelectRectangle)); gtk_widget_show (toolsSelectRectangle); gtk_container_add (GTK_CONTAINER (menuTools_menu), toolsSelectRectangle); + gtk_widget_add_accelerator (toolsSelectRectangle, "activate", accel_group, + GDK_R, (GdkModifierType) GDK_CONTROL_MASK | GDK_SHIFT_MASK, + GTK_ACCEL_VISIBLE); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (toolsSelectRectangle), TRUE); - toolsVerticalSpace = gtk_radio_menu_item_new_with_mnemonic (toolsPen_group, "Vertical Space"); + toolsVerticalSpace = gtk_radio_menu_item_new_with_mnemonic (toolsPen_group, "_Vertical Space"); toolsPen_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (toolsVerticalSpace)); gtk_widget_show (toolsVerticalSpace); gtk_container_add (GTK_CONTAINER (menuTools_menu), toolsVerticalSpace); + gtk_widget_add_accelerator (toolsVerticalSpace, "activate", accel_group, + GDK_V, (GdkModifierType) GDK_CONTROL_MASK | GDK_SHIFT_MASK, + GTK_ACCEL_VISIBLE); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (toolsVerticalSpace), TRUE); - toolsHand = gtk_radio_menu_item_new_with_mnemonic (toolsPen_group, "Hand Tool"); + toolsHand = gtk_radio_menu_item_new_with_mnemonic (toolsPen_group, "H_and Tool"); toolsPen_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (toolsHand)); gtk_widget_show (toolsHand); gtk_container_add (GTK_CONTAINER (menuTools_menu), toolsHand); + gtk_widget_add_accelerator (toolsHand, "activate", accel_group, + GDK_A, (GdkModifierType) GDK_CONTROL_MASK | GDK_SHIFT_MASK, + GTK_ACCEL_VISIBLE); separator16 = gtk_separator_menu_item_new (); gtk_widget_show (separator16); @@ -856,31 +926,31 @@ create_winMain (void) toolsColor_menu = gtk_menu_new (); gtk_menu_item_set_submenu (GTK_MENU_ITEM (toolsColor), toolsColor_menu); - colorBlack = gtk_radio_menu_item_new_with_mnemonic (colorBlack_group, "black"); + colorBlack = gtk_radio_menu_item_new_with_mnemonic (colorBlack_group, "blac_k"); colorBlack_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (colorBlack)); gtk_widget_show (colorBlack); gtk_container_add (GTK_CONTAINER (toolsColor_menu), colorBlack); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (colorBlack), TRUE); - colorBlue = gtk_radio_menu_item_new_with_mnemonic (colorBlack_group, "blue"); + colorBlue = gtk_radio_menu_item_new_with_mnemonic (colorBlack_group, "_blue"); colorBlack_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (colorBlue)); gtk_widget_show (colorBlue); gtk_container_add (GTK_CONTAINER (toolsColor_menu), colorBlue); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (colorBlue), TRUE); - colorRed = gtk_radio_menu_item_new_with_mnemonic (colorBlack_group, "red"); + colorRed = gtk_radio_menu_item_new_with_mnemonic (colorBlack_group, "_red"); colorBlack_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (colorRed)); gtk_widget_show (colorRed); gtk_container_add (GTK_CONTAINER (toolsColor_menu), colorRed); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (colorRed), TRUE); - colorGreen = gtk_radio_menu_item_new_with_mnemonic (colorBlack_group, "green"); + colorGreen = gtk_radio_menu_item_new_with_mnemonic (colorBlack_group, "_green"); colorBlack_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (colorGreen)); gtk_widget_show (colorGreen); gtk_container_add (GTK_CONTAINER (toolsColor_menu), colorGreen); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (colorGreen), TRUE); - colorGray = gtk_radio_menu_item_new_with_mnemonic (colorBlack_group, "gray"); + colorGray = gtk_radio_menu_item_new_with_mnemonic (colorBlack_group, "gr_ay"); colorBlack_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (colorGray)); gtk_widget_show (colorGray); gtk_container_add (GTK_CONTAINER (toolsColor_menu), colorGray); @@ -891,37 +961,37 @@ create_winMain (void) gtk_container_add (GTK_CONTAINER (toolsColor_menu), separator17); gtk_widget_set_sensitive (separator17, FALSE); - colorLightBlue = gtk_radio_menu_item_new_with_mnemonic (colorBlack_group, "light blue"); + colorLightBlue = gtk_radio_menu_item_new_with_mnemonic (colorBlack_group, "light bl_ue"); colorBlack_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (colorLightBlue)); gtk_widget_show (colorLightBlue); gtk_container_add (GTK_CONTAINER (toolsColor_menu), colorLightBlue); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (colorLightBlue), TRUE); - colorLightGreen = gtk_radio_menu_item_new_with_mnemonic (colorBlack_group, "light green"); + colorLightGreen = gtk_radio_menu_item_new_with_mnemonic (colorBlack_group, "light gr_een"); colorBlack_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (colorLightGreen)); gtk_widget_show (colorLightGreen); gtk_container_add (GTK_CONTAINER (toolsColor_menu), colorLightGreen); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (colorLightGreen), TRUE); - colorMagenta = gtk_radio_menu_item_new_with_mnemonic (colorBlack_group, "magenta"); + colorMagenta = gtk_radio_menu_item_new_with_mnemonic (colorBlack_group, "_magenta"); colorBlack_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (colorMagenta)); gtk_widget_show (colorMagenta); gtk_container_add (GTK_CONTAINER (toolsColor_menu), colorMagenta); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (colorMagenta), TRUE); - colorOrange = gtk_radio_menu_item_new_with_mnemonic (colorBlack_group, "orange"); + colorOrange = gtk_radio_menu_item_new_with_mnemonic (colorBlack_group, "_orange"); colorBlack_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (colorOrange)); gtk_widget_show (colorOrange); gtk_container_add (GTK_CONTAINER (toolsColor_menu), colorOrange); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (colorOrange), TRUE); - colorYellow = gtk_radio_menu_item_new_with_mnemonic (colorBlack_group, "yellow"); + colorYellow = gtk_radio_menu_item_new_with_mnemonic (colorBlack_group, "_yellow"); colorBlack_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (colorYellow)); gtk_widget_show (colorYellow); gtk_container_add (GTK_CONTAINER (toolsColor_menu), colorYellow); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (colorYellow), TRUE); - colorWhite = gtk_radio_menu_item_new_with_mnemonic (colorBlack_group, "white"); + colorWhite = gtk_radio_menu_item_new_with_mnemonic (colorBlack_group, "_white"); colorBlack_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (colorWhite)); gtk_widget_show (colorWhite); gtk_container_add (GTK_CONTAINER (toolsColor_menu), colorWhite); @@ -945,56 +1015,56 @@ create_winMain (void) toolsPenOptions_menu = gtk_menu_new (); gtk_menu_item_set_submenu (GTK_MENU_ITEM (toolsPenOptions), toolsPenOptions_menu); - penthicknessVeryFine = gtk_radio_menu_item_new_with_mnemonic (penthicknessVeryFine_group, "very fine"); + penthicknessVeryFine = gtk_radio_menu_item_new_with_mnemonic (penthicknessVeryFine_group, "_very fine"); penthicknessVeryFine_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (penthicknessVeryFine)); gtk_widget_show (penthicknessVeryFine); gtk_container_add (GTK_CONTAINER (toolsPenOptions_menu), penthicknessVeryFine); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (penthicknessVeryFine), TRUE); - penthicknessFine = gtk_radio_menu_item_new_with_mnemonic (penthicknessVeryFine_group, "fine"); + penthicknessFine = gtk_radio_menu_item_new_with_mnemonic (penthicknessVeryFine_group, "_fine"); penthicknessVeryFine_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (penthicknessFine)); gtk_widget_show (penthicknessFine); gtk_container_add (GTK_CONTAINER (toolsPenOptions_menu), penthicknessFine); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (penthicknessFine), TRUE); - penthicknessMedium = gtk_radio_menu_item_new_with_mnemonic (penthicknessVeryFine_group, "medium"); + penthicknessMedium = gtk_radio_menu_item_new_with_mnemonic (penthicknessVeryFine_group, "_medium"); penthicknessVeryFine_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (penthicknessMedium)); gtk_widget_show (penthicknessMedium); gtk_container_add (GTK_CONTAINER (toolsPenOptions_menu), penthicknessMedium); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (penthicknessMedium), TRUE); - penthicknessThick = gtk_radio_menu_item_new_with_mnemonic (penthicknessVeryFine_group, "thick"); + penthicknessThick = gtk_radio_menu_item_new_with_mnemonic (penthicknessVeryFine_group, "_thick"); penthicknessVeryFine_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (penthicknessThick)); gtk_widget_show (penthicknessThick); gtk_container_add (GTK_CONTAINER (toolsPenOptions_menu), penthicknessThick); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (penthicknessThick), TRUE); - penthicknessVeryThick = gtk_radio_menu_item_new_with_mnemonic (penthicknessVeryFine_group, "very thick"); + penthicknessVeryThick = gtk_radio_menu_item_new_with_mnemonic (penthicknessVeryFine_group, "ver_y thick"); penthicknessVeryFine_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (penthicknessVeryThick)); gtk_widget_show (penthicknessVeryThick); gtk_container_add (GTK_CONTAINER (toolsPenOptions_menu), penthicknessVeryThick); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (penthicknessVeryThick), TRUE); - toolsEraserOptions = gtk_menu_item_new_with_mnemonic ("Eraser Options"); + toolsEraserOptions = gtk_menu_item_new_with_mnemonic ("Eraser Optio_ns"); gtk_widget_show (toolsEraserOptions); gtk_container_add (GTK_CONTAINER (menuTools_menu), toolsEraserOptions); toolsEraserOptions_menu = gtk_menu_new (); gtk_menu_item_set_submenu (GTK_MENU_ITEM (toolsEraserOptions), toolsEraserOptions_menu); - eraserFine = gtk_radio_menu_item_new_with_mnemonic (eraserFine_group, "fine"); + eraserFine = gtk_radio_menu_item_new_with_mnemonic (eraserFine_group, "_fine"); eraserFine_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (eraserFine)); gtk_widget_show (eraserFine); gtk_container_add (GTK_CONTAINER (toolsEraserOptions_menu), eraserFine); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (eraserFine), TRUE); - eraserMedium = gtk_radio_menu_item_new_with_mnemonic (eraserFine_group, "medium"); + eraserMedium = gtk_radio_menu_item_new_with_mnemonic (eraserFine_group, "_medium"); eraserFine_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (eraserMedium)); gtk_widget_show (eraserMedium); gtk_container_add (GTK_CONTAINER (toolsEraserOptions_menu), eraserMedium); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (eraserMedium), TRUE); - eraserThick = gtk_radio_menu_item_new_with_mnemonic (eraserFine_group, "thick"); + eraserThick = gtk_radio_menu_item_new_with_mnemonic (eraserFine_group, "_thick"); eraserFine_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (eraserThick)); gtk_widget_show (eraserThick); gtk_container_add (GTK_CONTAINER (toolsEraserOptions_menu), eraserThick); @@ -1005,52 +1075,55 @@ create_winMain (void) gtk_container_add (GTK_CONTAINER (toolsEraserOptions_menu), separator14); gtk_widget_set_sensitive (separator14, FALSE); - eraserStandard = gtk_radio_menu_item_new_with_mnemonic (eraserStandard_group, "standard"); + eraserStandard = gtk_radio_menu_item_new_with_mnemonic (eraserStandard_group, "_standard"); eraserStandard_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (eraserStandard)); gtk_widget_show (eraserStandard); gtk_container_add (GTK_CONTAINER (toolsEraserOptions_menu), eraserStandard); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (eraserStandard), TRUE); - eraserWhiteout = gtk_radio_menu_item_new_with_mnemonic (eraserStandard_group, "whiteout"); + eraserWhiteout = gtk_radio_menu_item_new_with_mnemonic (eraserStandard_group, "_whiteout"); eraserStandard_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (eraserWhiteout)); gtk_widget_show (eraserWhiteout); gtk_container_add (GTK_CONTAINER (toolsEraserOptions_menu), eraserWhiteout); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (eraserWhiteout), TRUE); - eraserDeleteStrokes = gtk_radio_menu_item_new_with_mnemonic (eraserStandard_group, "delete strokes"); + eraserDeleteStrokes = gtk_radio_menu_item_new_with_mnemonic (eraserStandard_group, "_delete strokes"); eraserStandard_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (eraserDeleteStrokes)); gtk_widget_show (eraserDeleteStrokes); gtk_container_add (GTK_CONTAINER (toolsEraserOptions_menu), eraserDeleteStrokes); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (eraserDeleteStrokes), TRUE); - toolsHighlighterOptions = gtk_menu_item_new_with_mnemonic ("Highlighter Options"); + toolsHighlighterOptions = gtk_menu_item_new_with_mnemonic ("Highlighter Opt_ions"); gtk_widget_show (toolsHighlighterOptions); gtk_container_add (GTK_CONTAINER (menuTools_menu), toolsHighlighterOptions); toolsHighlighterOptions_menu = gtk_menu_new (); gtk_menu_item_set_submenu (GTK_MENU_ITEM (toolsHighlighterOptions), toolsHighlighterOptions_menu); - highlighterFine = gtk_radio_menu_item_new_with_mnemonic (highlighterFine_group, "fine"); + highlighterFine = gtk_radio_menu_item_new_with_mnemonic (highlighterFine_group, "_fine"); highlighterFine_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (highlighterFine)); gtk_widget_show (highlighterFine); gtk_container_add (GTK_CONTAINER (toolsHighlighterOptions_menu), highlighterFine); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (highlighterFine), TRUE); - highlighterMedium = gtk_radio_menu_item_new_with_mnemonic (highlighterFine_group, "medium"); + highlighterMedium = gtk_radio_menu_item_new_with_mnemonic (highlighterFine_group, "_medium"); highlighterFine_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (highlighterMedium)); gtk_widget_show (highlighterMedium); gtk_container_add (GTK_CONTAINER (toolsHighlighterOptions_menu), highlighterMedium); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (highlighterMedium), TRUE); - highlighterThick = gtk_radio_menu_item_new_with_mnemonic (highlighterFine_group, "thick"); + highlighterThick = gtk_radio_menu_item_new_with_mnemonic (highlighterFine_group, "_thick"); highlighterFine_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (highlighterThick)); gtk_widget_show (highlighterThick); gtk_container_add (GTK_CONTAINER (toolsHighlighterOptions_menu), highlighterThick); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (highlighterThick), TRUE); - toolsTextFont = gtk_image_menu_item_new_with_mnemonic ("Text Font"); + toolsTextFont = gtk_image_menu_item_new_with_mnemonic ("Text _Font..."); gtk_widget_show (toolsTextFont); gtk_container_add (GTK_CONTAINER (menuTools_menu), toolsTextFont); + gtk_widget_add_accelerator (toolsTextFont, "activate", accel_group, + GDK_F, (GdkModifierType) GDK_CONTROL_MASK | GDK_SHIFT_MASK, + GTK_ACCEL_VISIBLE); image634 = gtk_image_new_from_stock ("gtk-select-font", GTK_ICON_SIZE_MENU); gtk_widget_show (image634); @@ -1061,7 +1134,7 @@ create_winMain (void) gtk_container_add (GTK_CONTAINER (menuTools_menu), separator10); gtk_widget_set_sensitive (separator10, FALSE); - toolsDefaultPen = gtk_menu_item_new_with_mnemonic ("Default Pen"); + toolsDefaultPen = gtk_menu_item_new_with_mnemonic ("_Default Pen"); gtk_widget_show (toolsDefaultPen); gtk_container_add (GTK_CONTAINER (menuTools_menu), toolsDefaultPen); @@ -1073,11 +1146,11 @@ create_winMain (void) gtk_widget_show (toolsDefaultHighlighter); gtk_container_add (GTK_CONTAINER (menuTools_menu), toolsDefaultHighlighter); - toolsDefaultText = gtk_menu_item_new_with_mnemonic ("Default Text"); + toolsDefaultText = gtk_menu_item_new_with_mnemonic ("Default Te_xt"); gtk_widget_show (toolsDefaultText); gtk_container_add (GTK_CONTAINER (menuTools_menu), toolsDefaultText); - toolsSetAsDefault = gtk_menu_item_new_with_mnemonic ("Set As Default"); + toolsSetAsDefault = gtk_menu_item_new_with_mnemonic ("_Set As Default"); gtk_widget_show (toolsSetAsDefault); gtk_container_add (GTK_CONTAINER (menuTools_menu), toolsSetAsDefault); @@ -1086,9 +1159,12 @@ create_winMain (void) gtk_container_add (GTK_CONTAINER (menuTools_menu), separator15); gtk_widget_set_sensitive (separator15, FALSE); - toolsRuler = gtk_check_menu_item_new_with_mnemonic ("Ruler"); + toolsRuler = gtk_check_menu_item_new_with_mnemonic ("Ru_ler"); gtk_widget_show (toolsRuler); gtk_container_add (GTK_CONTAINER (menuTools_menu), toolsRuler); + gtk_widget_add_accelerator (toolsRuler, "activate", accel_group, + GDK_L, (GdkModifierType) GDK_CONTROL_MASK | GDK_SHIFT_MASK, + GTK_ACCEL_VISIBLE); menuOptions = gtk_menu_item_new_with_mnemonic ("_Options"); gtk_widget_show (menuOptions); @@ -1097,68 +1173,68 @@ create_winMain (void) menuOptions_menu = gtk_menu_new (); gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuOptions), menuOptions_menu); - optionsUseXInput = gtk_check_menu_item_new_with_mnemonic ("Use XInput"); + optionsUseXInput = gtk_check_menu_item_new_with_mnemonic ("Use _XInput"); gtk_widget_show (optionsUseXInput); gtk_container_add (GTK_CONTAINER (menuOptions_menu), optionsUseXInput); - optionsDiscardCoreEvents = gtk_check_menu_item_new_with_mnemonic ("Discard Core Events"); + optionsDiscardCoreEvents = gtk_check_menu_item_new_with_mnemonic ("Discard _Core Events"); gtk_widget_show (optionsDiscardCoreEvents); gtk_container_add (GTK_CONTAINER (menuOptions_menu), optionsDiscardCoreEvents); - optionsButtonMappings = gtk_check_menu_item_new_with_mnemonic ("Eraser Tip"); + optionsButtonMappings = gtk_check_menu_item_new_with_mnemonic ("_Eraser Tip"); gtk_widget_show (optionsButtonMappings); gtk_container_add (GTK_CONTAINER (menuOptions_menu), optionsButtonMappings); - button2_mapping = gtk_menu_item_new_with_mnemonic ("Button 2 Mapping"); + button2_mapping = gtk_menu_item_new_with_mnemonic ("Button _2 Mapping"); gtk_widget_show (button2_mapping); gtk_container_add (GTK_CONTAINER (menuOptions_menu), button2_mapping); button2_mapping_menu = gtk_menu_new (); gtk_menu_item_set_submenu (GTK_MENU_ITEM (button2_mapping), button2_mapping_menu); - button2Pen = gtk_radio_menu_item_new_with_mnemonic (button2Pen_group, "Pen"); + button2Pen = gtk_radio_menu_item_new_with_mnemonic (button2Pen_group, "_Pen"); button2Pen_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (button2Pen)); gtk_widget_show (button2Pen); gtk_container_add (GTK_CONTAINER (button2_mapping_menu), button2Pen); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (button2Pen), TRUE); - button2Eraser = gtk_radio_menu_item_new_with_mnemonic (button2Pen_group, "Eraser"); + button2Eraser = gtk_radio_menu_item_new_with_mnemonic (button2Pen_group, "_Eraser"); button2Pen_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (button2Eraser)); gtk_widget_show (button2Eraser); gtk_container_add (GTK_CONTAINER (button2_mapping_menu), button2Eraser); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (button2Eraser), TRUE); - button2Highlighter = gtk_radio_menu_item_new_with_mnemonic (button2Pen_group, "Highlighter"); + button2Highlighter = gtk_radio_menu_item_new_with_mnemonic (button2Pen_group, "_Highlighter"); button2Pen_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (button2Highlighter)); gtk_widget_show (button2Highlighter); gtk_container_add (GTK_CONTAINER (button2_mapping_menu), button2Highlighter); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (button2Highlighter), TRUE); - button2Text = gtk_radio_menu_item_new_with_mnemonic (button2Pen_group, "Text"); + button2Text = gtk_radio_menu_item_new_with_mnemonic (button2Pen_group, "_Text"); button2Pen_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (button2Text)); gtk_widget_show (button2Text); gtk_container_add (GTK_CONTAINER (button2_mapping_menu), button2Text); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (button2Text), TRUE); - button2SelectRegion = gtk_radio_menu_item_new_with_mnemonic (button2Pen_group, "Select Region"); + button2SelectRegion = gtk_radio_menu_item_new_with_mnemonic (button2Pen_group, "Select Re_gion"); button2Pen_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (button2SelectRegion)); gtk_widget_show (button2SelectRegion); gtk_container_add (GTK_CONTAINER (button2_mapping_menu), button2SelectRegion); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (button2SelectRegion), TRUE); - button2SelectRectangle = gtk_radio_menu_item_new_with_mnemonic (button2Pen_group, "Select Rectangle"); + button2SelectRectangle = gtk_radio_menu_item_new_with_mnemonic (button2Pen_group, "Select _Rectangle"); button2Pen_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (button2SelectRectangle)); gtk_widget_show (button2SelectRectangle); gtk_container_add (GTK_CONTAINER (button2_mapping_menu), button2SelectRectangle); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (button2SelectRectangle), TRUE); - button2VerticalSpace = gtk_radio_menu_item_new_with_mnemonic (button2Pen_group, "Vertical Space"); + button2VerticalSpace = gtk_radio_menu_item_new_with_mnemonic (button2Pen_group, "_Vertical Space"); button2Pen_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (button2VerticalSpace)); gtk_widget_show (button2VerticalSpace); gtk_container_add (GTK_CONTAINER (button2_mapping_menu), button2VerticalSpace); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (button2VerticalSpace), TRUE); - button2Hand = gtk_radio_menu_item_new_with_mnemonic (button2Pen_group, "Hand Tool"); + button2Hand = gtk_radio_menu_item_new_with_mnemonic (button2Pen_group, "H_and Tool"); button2Pen_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (button2Hand)); gtk_widget_show (button2Hand); gtk_container_add (GTK_CONTAINER (button2_mapping_menu), button2Hand); @@ -1168,13 +1244,13 @@ create_winMain (void) gtk_container_add (GTK_CONTAINER (button2_mapping_menu), separator24); gtk_widget_set_sensitive (separator24, FALSE); - button2LinkBrush = gtk_radio_menu_item_new_with_mnemonic (button2LinkBrush_group, "Link to Primary Brush"); + button2LinkBrush = gtk_radio_menu_item_new_with_mnemonic (button2LinkBrush_group, "_Link to Primary Brush"); button2LinkBrush_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (button2LinkBrush)); gtk_widget_show (button2LinkBrush); gtk_container_add (GTK_CONTAINER (button2_mapping_menu), button2LinkBrush); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (button2LinkBrush), TRUE); - button2CopyBrush = gtk_radio_menu_item_new_with_mnemonic (button2LinkBrush_group, "Copy of Current Brush"); + button2CopyBrush = gtk_radio_menu_item_new_with_mnemonic (button2LinkBrush_group, "_Copy of Current Brush"); button2LinkBrush_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (button2CopyBrush)); gtk_widget_show (button2CopyBrush); gtk_container_add (GTK_CONTAINER (button2_mapping_menu), button2CopyBrush); @@ -1185,56 +1261,56 @@ create_winMain (void) gtk_container_add (GTK_CONTAINER (button2_mapping_menu), button2NABrush); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (button2NABrush), TRUE); - button3_mapping = gtk_menu_item_new_with_mnemonic ("Button 3 Mapping"); + button3_mapping = gtk_menu_item_new_with_mnemonic ("Button _3 Mapping"); gtk_widget_show (button3_mapping); gtk_container_add (GTK_CONTAINER (menuOptions_menu), button3_mapping); button3_mapping_menu = gtk_menu_new (); gtk_menu_item_set_submenu (GTK_MENU_ITEM (button3_mapping), button3_mapping_menu); - button3Pen = gtk_radio_menu_item_new_with_mnemonic (button3Pen_group, "Pen"); + button3Pen = gtk_radio_menu_item_new_with_mnemonic (button3Pen_group, "_Pen"); button3Pen_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (button3Pen)); gtk_widget_show (button3Pen); gtk_container_add (GTK_CONTAINER (button3_mapping_menu), button3Pen); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (button3Pen), TRUE); - button3Eraser = gtk_radio_menu_item_new_with_mnemonic (button3Pen_group, "Eraser"); + button3Eraser = gtk_radio_menu_item_new_with_mnemonic (button3Pen_group, "_Eraser"); button3Pen_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (button3Eraser)); gtk_widget_show (button3Eraser); gtk_container_add (GTK_CONTAINER (button3_mapping_menu), button3Eraser); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (button3Eraser), TRUE); - button3Highlighter = gtk_radio_menu_item_new_with_mnemonic (button3Pen_group, "Highlighter"); + button3Highlighter = gtk_radio_menu_item_new_with_mnemonic (button3Pen_group, "_Highlighter"); button3Pen_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (button3Highlighter)); gtk_widget_show (button3Highlighter); gtk_container_add (GTK_CONTAINER (button3_mapping_menu), button3Highlighter); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (button3Highlighter), TRUE); - button3Text = gtk_radio_menu_item_new_with_mnemonic (button3Pen_group, "Text"); + button3Text = gtk_radio_menu_item_new_with_mnemonic (button3Pen_group, "_Text"); button3Pen_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (button3Text)); gtk_widget_show (button3Text); gtk_container_add (GTK_CONTAINER (button3_mapping_menu), button3Text); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (button3Text), TRUE); - button3SelectRegion = gtk_radio_menu_item_new_with_mnemonic (button3Pen_group, "Select Region"); + button3SelectRegion = gtk_radio_menu_item_new_with_mnemonic (button3Pen_group, "Select Re_gion"); button3Pen_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (button3SelectRegion)); gtk_widget_show (button3SelectRegion); gtk_container_add (GTK_CONTAINER (button3_mapping_menu), button3SelectRegion); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (button3SelectRegion), TRUE); - button3SelectRectangle = gtk_radio_menu_item_new_with_mnemonic (button3Pen_group, "Select Rectangle"); + button3SelectRectangle = gtk_radio_menu_item_new_with_mnemonic (button3Pen_group, "Select _Rectangle"); button3Pen_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (button3SelectRectangle)); gtk_widget_show (button3SelectRectangle); gtk_container_add (GTK_CONTAINER (button3_mapping_menu), button3SelectRectangle); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (button3SelectRectangle), TRUE); - button3VerticalSpace = gtk_radio_menu_item_new_with_mnemonic (button3Pen_group, "Vertical Space"); + button3VerticalSpace = gtk_radio_menu_item_new_with_mnemonic (button3Pen_group, "_Vertical Space"); button3Pen_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (button3VerticalSpace)); gtk_widget_show (button3VerticalSpace); gtk_container_add (GTK_CONTAINER (button3_mapping_menu), button3VerticalSpace); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (button3VerticalSpace), TRUE); - button3Hand = gtk_radio_menu_item_new_with_mnemonic (button3Pen_group, "Hand Tool"); + button3Hand = gtk_radio_menu_item_new_with_mnemonic (button3Pen_group, "H_and Tool"); button3Pen_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (button3Hand)); gtk_widget_show (button3Hand); gtk_container_add (GTK_CONTAINER (button3_mapping_menu), button3Hand); @@ -1244,13 +1320,13 @@ create_winMain (void) gtk_container_add (GTK_CONTAINER (button3_mapping_menu), separator25); gtk_widget_set_sensitive (separator25, FALSE); - button3LinkBrush = gtk_radio_menu_item_new_with_mnemonic (button3LinkBrush_group, "Link to Primary Brush"); + button3LinkBrush = gtk_radio_menu_item_new_with_mnemonic (button3LinkBrush_group, "_Link to Primary Brush"); button3LinkBrush_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (button3LinkBrush)); gtk_widget_show (button3LinkBrush); gtk_container_add (GTK_CONTAINER (button3_mapping_menu), button3LinkBrush); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (button3LinkBrush), TRUE); - button3CopyBrush = gtk_radio_menu_item_new_with_mnemonic (button3LinkBrush_group, "Copy of Current Brush"); + button3CopyBrush = gtk_radio_menu_item_new_with_mnemonic (button3LinkBrush_group, "_Copy of Current Brush"); button3LinkBrush_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (button3CopyBrush)); gtk_widget_show (button3CopyBrush); gtk_container_add (GTK_CONTAINER (button3_mapping_menu), button3CopyBrush); @@ -1266,15 +1342,15 @@ create_winMain (void) gtk_container_add (GTK_CONTAINER (menuOptions_menu), separator18); gtk_widget_set_sensitive (separator18, FALSE); - optionsAntialiasBG = gtk_check_menu_item_new_with_mnemonic ("Antialiased Bitmaps"); + optionsAntialiasBG = gtk_check_menu_item_new_with_mnemonic ("_Antialiased Bitmaps"); gtk_widget_show (optionsAntialiasBG); gtk_container_add (GTK_CONTAINER (menuOptions_menu), optionsAntialiasBG); - optionsProgressiveBG = gtk_check_menu_item_new_with_mnemonic ("Progressive Backgrounds"); + optionsProgressiveBG = gtk_check_menu_item_new_with_mnemonic ("_Progressive Backgrounds"); gtk_widget_show (optionsProgressiveBG); gtk_container_add (GTK_CONTAINER (menuOptions_menu), optionsProgressiveBG); - optionsPrintRuling = gtk_check_menu_item_new_with_mnemonic ("Print Paper Ruling"); + optionsPrintRuling = gtk_check_menu_item_new_with_mnemonic ("Print Paper _Ruling"); gtk_widget_show (optionsPrintRuling); gtk_container_add (GTK_CONTAINER (menuOptions_menu), optionsPrintRuling); @@ -1283,7 +1359,7 @@ create_winMain (void) gtk_container_add (GTK_CONTAINER (menuOptions_menu), separator21); gtk_widget_set_sensitive (separator21, FALSE); - optionsSavePreferences = gtk_menu_item_new_with_mnemonic ("Save Preferences"); + optionsSavePreferences = gtk_menu_item_new_with_mnemonic ("_Save Preferences"); gtk_widget_show (optionsSavePreferences); gtk_container_add (GTK_CONTAINER (menuOptions_menu), optionsSavePreferences); @@ -1767,6 +1843,24 @@ create_winMain (void) gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonColorOther), buttonBlack_group); buttonBlack_group = gtk_radio_tool_button_get_group (GTK_RADIO_TOOL_BUTTON (buttonColorOther)); + toolitem21 = (GtkWidget*) gtk_tool_item_new (); + gtk_widget_show (toolitem21); + gtk_container_add (GTK_CONTAINER (toolbarPen), toolitem21); + + vseparator10 = gtk_vseparator_new (); + gtk_widget_show (vseparator10); + gtk_container_add (GTK_CONTAINER (toolitem21), vseparator10); + + toolitem20 = (GtkWidget*) gtk_tool_item_new (); + gtk_widget_show (toolitem20); + gtk_container_add (GTK_CONTAINER (toolbarPen), toolitem20); + + fontButton = gtk_font_button_new (); + gtk_widget_show (fontButton); + gtk_container_add (GTK_CONTAINER (toolitem20), fontButton); + gtk_font_button_set_use_font (GTK_FONT_BUTTON (fontButton), TRUE); + gtk_button_set_focus_on_click (GTK_BUTTON (fontButton), FALSE); + scrolledwindowMain = gtk_scrolled_window_new (NULL, NULL); gtk_widget_show (scrolledwindowMain); gtk_box_pack_start (GTK_BOX (vboxMain), scrolledwindowMain, TRUE, TRUE, 0); @@ -2333,6 +2427,9 @@ create_winMain (void) g_signal_connect ((gpointer) buttonWhite, "toggled", G_CALLBACK (on_colorWhite_activate), NULL); + g_signal_connect ((gpointer) fontButton, "font_set", + G_CALLBACK (on_fontButton_font_set), + NULL); g_signal_connect ((gpointer) spinPageNo, "value_changed", G_CALLBACK (on_spinPageNo_value_changed), NULL); @@ -2611,6 +2708,10 @@ create_winMain (void) GLADE_HOOKUP_OBJECT (winMain, buttonYellow, "buttonYellow"); GLADE_HOOKUP_OBJECT (winMain, buttonWhite, "buttonWhite"); GLADE_HOOKUP_OBJECT (winMain, buttonColorOther, "buttonColorOther"); + GLADE_HOOKUP_OBJECT (winMain, toolitem21, "toolitem21"); + GLADE_HOOKUP_OBJECT (winMain, vseparator10, "vseparator10"); + GLADE_HOOKUP_OBJECT (winMain, toolitem20, "toolitem20"); + GLADE_HOOKUP_OBJECT (winMain, fontButton, "fontButton"); GLADE_HOOKUP_OBJECT (winMain, scrolledwindowMain, "scrolledwindowMain"); GLADE_HOOKUP_OBJECT (winMain, hbox1, "hbox1"); GLADE_HOOKUP_OBJECT (winMain, labelPage, "labelPage"); @@ -2627,84 +2728,6 @@ create_winMain (void) return winMain; } -GtkWidget* -create_fontDialog (void) -{ - GtkWidget *fontDialog; - GtkWidget *ok_button1; - GtkWidget *cancel_button1; - GtkWidget *apply_button1; - GtkWidget *font_selection1; - - fontDialog = gtk_font_selection_dialog_new ("Select Font"); - gtk_container_set_border_width (GTK_CONTAINER (fontDialog), 4); - gtk_window_set_type_hint (GTK_WINDOW (fontDialog), GDK_WINDOW_TYPE_HINT_DIALOG); - - ok_button1 = GTK_FONT_SELECTION_DIALOG (fontDialog)->ok_button; - gtk_widget_show (ok_button1); - GTK_WIDGET_SET_FLAGS (ok_button1, GTK_CAN_DEFAULT); - - cancel_button1 = GTK_FONT_SELECTION_DIALOG (fontDialog)->cancel_button; - gtk_widget_show (cancel_button1); - GTK_WIDGET_SET_FLAGS (cancel_button1, GTK_CAN_DEFAULT); - - apply_button1 = GTK_FONT_SELECTION_DIALOG (fontDialog)->apply_button; - gtk_widget_show (apply_button1); - GTK_WIDGET_SET_FLAGS (apply_button1, GTK_CAN_DEFAULT); - - font_selection1 = GTK_FONT_SELECTION_DIALOG (fontDialog)->fontsel; - gtk_widget_show (font_selection1); - gtk_container_set_border_width (GTK_CONTAINER (font_selection1), 4); - - /* Store pointers to all widgets, for use by lookup_widget(). */ - GLADE_HOOKUP_OBJECT_NO_REF (fontDialog, fontDialog, "fontDialog"); - GLADE_HOOKUP_OBJECT_NO_REF (fontDialog, ok_button1, "ok_button1"); - GLADE_HOOKUP_OBJECT_NO_REF (fontDialog, cancel_button1, "cancel_button1"); - GLADE_HOOKUP_OBJECT_NO_REF (fontDialog, apply_button1, "apply_button1"); - GLADE_HOOKUP_OBJECT_NO_REF (fontDialog, font_selection1, "font_selection1"); - - return fontDialog; -} - -GtkWidget* -create_colorChooserDialog (void) -{ - GtkWidget *colorChooserDialog; - GtkWidget *ok_button2; - GtkWidget *cancel_button2; - GtkWidget *help_button1; - GtkWidget *color_selection1; - - colorChooserDialog = gtk_color_selection_dialog_new ("Select Color"); - gtk_window_set_resizable (GTK_WINDOW (colorChooserDialog), FALSE); - gtk_window_set_type_hint (GTK_WINDOW (colorChooserDialog), GDK_WINDOW_TYPE_HINT_DIALOG); - - ok_button2 = GTK_COLOR_SELECTION_DIALOG (colorChooserDialog)->ok_button; - gtk_widget_show (ok_button2); - GTK_WIDGET_SET_FLAGS (ok_button2, GTK_CAN_DEFAULT); - - cancel_button2 = GTK_COLOR_SELECTION_DIALOG (colorChooserDialog)->cancel_button; - gtk_widget_show (cancel_button2); - GTK_WIDGET_SET_FLAGS (cancel_button2, GTK_CAN_DEFAULT); - - help_button1 = GTK_COLOR_SELECTION_DIALOG (colorChooserDialog)->help_button; - gtk_widget_show (help_button1); - GTK_WIDGET_SET_FLAGS (help_button1, GTK_CAN_DEFAULT); - - color_selection1 = GTK_COLOR_SELECTION_DIALOG (colorChooserDialog)->colorsel; - gtk_widget_show (color_selection1); - gtk_color_selection_set_has_opacity_control (GTK_COLOR_SELECTION (color_selection1), FALSE); - - /* Store pointers to all widgets, for use by lookup_widget(). */ - GLADE_HOOKUP_OBJECT_NO_REF (colorChooserDialog, colorChooserDialog, "colorChooserDialog"); - GLADE_HOOKUP_OBJECT_NO_REF (colorChooserDialog, ok_button2, "ok_button2"); - GLADE_HOOKUP_OBJECT_NO_REF (colorChooserDialog, cancel_button2, "cancel_button2"); - GLADE_HOOKUP_OBJECT_NO_REF (colorChooserDialog, help_button1, "help_button1"); - GLADE_HOOKUP_OBJECT_NO_REF (colorChooserDialog, color_selection1, "color_selection1"); - - return colorChooserDialog; -} - GtkWidget* create_papersizeDialog (void) { diff --git a/src/xo-interface.h b/src/xo-interface.h index 08921ca..1e86792 100644 --- a/src/xo-interface.h +++ b/src/xo-interface.h @@ -3,8 +3,6 @@ */ GtkWidget* create_winMain (void); -GtkWidget* create_fontDialog (void); -GtkWidget* create_colorChooserDialog (void); GtkWidget* create_papersizeDialog (void); GtkWidget* create_aboutDialog (void); GtkWidget* create_zoomDialog (void); diff --git a/src/xo-misc.c b/src/xo-misc.c index 7cfe984..619ab17 100644 --- a/src/xo-misc.c +++ b/src/xo-misc.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "xournal.h" #include "xo-interface.h" @@ -126,6 +127,11 @@ void clear_redo_stack(void) g_free(redo->item); /* the strokes are unmapped, so there are no associated canvas items */ } + else if (redo->type == ITEM_TEXT) { + g_free(redo->item->text); + g_free(redo->item->font_name); + g_free(redo->item); + } else if (redo->type == ITEM_ERASURE) { for (list = redo->erasurelist; list!=NULL; list=list->next) { erasure = (struct UndoErasureData *)list->data; @@ -165,6 +171,10 @@ void clear_redo_stack(void) else if (redo->type == ITEM_NEW_LAYER) { g_free(redo->layer); } + else if (redo->type == ITEM_TEXT_EDIT || redo->type == ITEM_TEXT_ATTRIB) { + g_free(redo->str); + if (redo->type == ITEM_TEXT_ATTRIB) g_free(redo->brush); + } u = redo; redo = redo->next; @@ -185,7 +195,10 @@ void clear_undo_stack(void) if (undo->type == ITEM_ERASURE) { for (list = undo->erasurelist; list!=NULL; list=list->next) { erasure = (struct UndoErasureData *)list->data; - gnome_canvas_points_free(erasure->item->path); + if (erasure->item->type == ITEM_STROKE) + gnome_canvas_points_free(erasure->item->path); + if (erasure->item->type == ITEM_TEXT) + { g_free(erasure->item->text); g_free(erasure->item->font_name); } g_free(erasure->item); g_list_free(erasure->replacement_items); g_free(erasure); @@ -214,6 +227,10 @@ void clear_undo_stack(void) undo->page->group = NULL; delete_page(undo->page); } + else if (undo->type == ITEM_TEXT_EDIT || undo->type == ITEM_TEXT_ATTRIB) { + g_free(undo->str); + if (undo->type == ITEM_TEXT_ATTRIB) g_free(undo->brush); + } u = undo; undo = undo->next; @@ -260,6 +277,9 @@ void delete_layer(struct Layer *l) item = (struct Item *)l->items->data; if (item->type == ITEM_STROKE && item->path != NULL) gnome_canvas_points_free(item->path); + if (item->type == ITEM_TEXT) { + g_free(item->font_name); g_free(item->text); + } // don't need to delete the canvas_item, as it's part of the group destroyed below g_free(item); l->items = g_list_delete_link(l->items, l->items); @@ -310,10 +330,11 @@ void get_pointer_coords(GdkEvent *event, gdouble *ret) void fix_xinput_coords(GdkEvent *event) { +#ifdef ENABLE_XINPUT_BUGFIX double *axes, *px, *py, axis_width; GdkDevice *device; int wx, wy, sx, sy; - + if (event->type == GDK_BUTTON_PRESS || event->type == GDK_BUTTON_RELEASE) { axes = event->button.axes; px = &(event->button.x); @@ -329,7 +350,9 @@ void fix_xinput_coords(GdkEvent *event) else return; // nothing we know how to do gdk_window_get_origin(event->any.window, &wx, &wy); - gnome_canvas_get_scroll_offsets(canvas, &sx, &sy); + // somehow, behavior changed starting with GTK+ 2.11.0 + if (!gtk_check_version(2, 11, 0)) sx = sy = 0; + else gnome_canvas_get_scroll_offsets(canvas, &sx, &sy); axis_width = device->axes[0].max - device->axes[0].min; if (axis_width>EPSILON) @@ -338,12 +361,13 @@ void fix_xinput_coords(GdkEvent *event) axis_width = device->axes[1].max - device->axes[1].min; if (axis_width>EPSILON) *py = (axes[1]/axis_width)*ui.screen_height + sy - wy; +#endif } void update_item_bbox(struct Item *item) { int i; - double *p; + gdouble *p, h, w; if (item->type == ITEM_STROKE) { item->bbox.left = item->bbox.right = item->path->coords[0]; @@ -356,6 +380,12 @@ void update_item_bbox(struct Item *item) if (p[1] > item->bbox.bottom) item->bbox.bottom = p[1]; } } + if (item->type == ITEM_TEXT && item->canvas_item!=NULL) { + h=0.; w=0.; + g_object_get(item->canvas_item, "text_width", &w, "text_height", &h, NULL); + item->bbox.right = item->bbox.left + w; + item->bbox.bottom = item->bbox.top + h; + } } void make_page_clipbox(struct Page *pg) @@ -372,6 +402,30 @@ void make_page_clipbox(struct Page *pg) gnome_canvas_path_def_unref(pg_clip); } +void make_canvas_item_one(GnomeCanvasGroup *group, struct Item *item) +{ + GnomeCanvasItem *i; + PangoFontDescription *font_desc; + + if (item->type == ITEM_STROKE) + item->canvas_item = gnome_canvas_item_new(group, + gnome_canvas_line_get_type(), "points", item->path, + "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND, + "fill-color-rgba", item->brush.color_rgba, + "width-units", item->brush.thickness, NULL); + if (item->type == ITEM_TEXT) { + font_desc = pango_font_description_from_string(item->font_name); + pango_font_description_set_absolute_size(font_desc, + item->font_size*ui.zoom*PANGO_SCALE); + item->canvas_item = gnome_canvas_item_new(group, + gnome_canvas_text_get_type(), + "x", item->bbox.left, "y", item->bbox.top, "anchor", GTK_ANCHOR_NW, + "font-desc", font_desc, "fill-color-rgba", item->brush.color_rgba, + "text", item->text, NULL); + update_item_bbox(item); + } +} + void make_canvas_items(void) { struct Page *pg; @@ -394,13 +448,8 @@ void make_canvas_items(void) pg->group, gnome_canvas_group_get_type(), NULL); for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next) { item = (struct Item *)itemlist->data; - if (item->type == ITEM_STROKE && item->canvas_item == NULL) { - item->canvas_item = gnome_canvas_item_new(l->group, - gnome_canvas_line_get_type(), "points", item->path, - "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND, - "fill-color-rgba", item->brush.color_rgba, - "width-units", item->brush.thickness, NULL); - } + if (item->canvas_item == NULL) + make_canvas_item_one(l->group, item); } } } @@ -586,6 +635,14 @@ void lower_canvas_item_to(GnomeCanvasGroup *g, GnomeCanvasItem *item, GnomeCanva g->item_list_end = g_list_last(g->item_list); } +void rgb_to_gdkcolor(guint rgba, GdkColor *color) +{ + color->pixel = 0; + color->red = ((rgba>>24)&0xff)*0x101; + color->green = ((rgba>>16)&0xff)*0x101; + color->blue = ((rgba>>8)&0xff)*0x101; +} + // some interface functions void update_thickness_buttons(void) @@ -616,7 +673,7 @@ void update_thickness_buttons(void) void update_color_buttons(void) { if (ui.selection!=NULL || (ui.toolno[ui.cur_mapping] != TOOL_PEN - && ui.toolno[ui.cur_mapping] != TOOL_HIGHLIGHTER)) { + && ui.toolno[ui.cur_mapping] != TOOL_HIGHLIGHTER && ui.toolno[ui.cur_mapping] != TOOL_TEXT)) { gtk_toggle_tool_button_set_active( GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonColorOther")), TRUE); } else @@ -766,7 +823,7 @@ void update_ruler_indicator(void) void update_color_menu(void) { if (ui.selection!=NULL || (ui.toolno[ui.cur_mapping] != TOOL_PEN - && ui.toolno[ui.cur_mapping] != TOOL_HIGHLIGHTER)) { + && ui.toolno[ui.cur_mapping] != TOOL_HIGHLIGHTER && ui.toolno[ui.cur_mapping] != TOOL_TEXT)) { gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorNA")), TRUE); } else @@ -928,7 +985,8 @@ void update_mappings_menu_linkings(void) void update_mappings_menu(void) { gtk_widget_set_sensitive(GET_COMPONENT("optionsButtonMappings"), ui.use_xinput); - gtk_widget_set_sensitive(GET_COMPONENT("optionsDiscardCoreEvents"), ui.use_xinput); + gtk_widget_set_sensitive(GET_COMPONENT("optionsDiscardCoreEvents"), + ui.use_xinput && (gtk_check_version(2, 11, 0)!=NULL)); gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(GET_COMPONENT("optionsButtonMappings")), ui.use_erasertip); gtk_check_menu_item_set_active( @@ -999,7 +1057,7 @@ void update_mappings_menu(void) void do_switch_page(int pg, gboolean rescroll, gboolean refresh_all) { - int i; + int i, cx, cy; struct Layer *layer; GList *list; @@ -1020,8 +1078,13 @@ void do_switch_page(int pg, gboolean rescroll, gboolean refresh_all) if (ui.progressive_bg) rescale_bg_pixmaps(); if (rescroll) { // scroll and force a refresh +/* -- this seems to cause some display bugs ?? gtk_adjustment_set_value(gtk_layout_get_vadjustment(GTK_LAYOUT(canvas)), - ui.cur_page->voffset*ui.zoom); + ui.cur_page->voffset*ui.zoom); */ + gnome_canvas_get_scroll_offsets(canvas, &cx, &cy); + cy = ui.cur_page->voffset*ui.zoom; + gnome_canvas_scroll_to(canvas, cx, cy); + if (refresh_all) gnome_canvas_set_pixels_per_unit(canvas, ui.zoom); else if (!ui.view_continuous) @@ -1232,9 +1295,11 @@ void update_copy_paste_enabled(void) { gtk_widget_set_sensitive(GET_COMPONENT("editCut"), ui.selection!=NULL); gtk_widget_set_sensitive(GET_COMPONENT("editCopy"), ui.selection!=NULL); + gtk_widget_set_sensitive(GET_COMPONENT("editPaste"), ui.cur_item_type!=ITEM_TEXT); gtk_widget_set_sensitive(GET_COMPONENT("editDelete"), ui.selection!=NULL); gtk_widget_set_sensitive(GET_COMPONENT("buttonCut"), ui.selection!=NULL); gtk_widget_set_sensitive(GET_COMPONENT("buttonCopy"), ui.selection!=NULL); + gtk_widget_set_sensitive(GET_COMPONENT("buttonPaste"), ui.cur_item_type!=ITEM_TEXT); } void update_mapping_linkings(int toolno) @@ -1260,12 +1325,32 @@ void set_cur_color(int color) { ui.cur_brush->color_no = color; if (ui.toolno[0] == TOOL_HIGHLIGHTER) - ui.cur_brush->color_rgba = predef_colors_rgba[color] & HILITER_ALPHA_MASK; + ui.cur_brush->color_rgba = predef_colors_rgba[color] & ui.hiliter_alpha_mask; else ui.cur_brush->color_rgba = predef_colors_rgba[color]; update_mapping_linkings(ui.toolno[0]); } +void recolor_temp_text(int color_no, guint color_rgba) +{ + GdkColor gdkcolor; + + if (ui.cur_item_type!=ITEM_TEXT) return; + if (ui.cur_item->text!=NULL && ui.cur_item->brush.color_rgba != color_rgba) { + prepare_new_undo(); + undo->type = ITEM_TEXT_ATTRIB; + undo->item = ui.cur_item; + undo->str = g_strdup(ui.cur_item->font_name); + undo->val_x = ui.cur_item->font_size; + undo->brush = (struct Brush *)g_memdup(&(ui.cur_item->brush), sizeof(struct Brush)); + } + ui.cur_item->brush.color_no = color_no; + ui.cur_item->brush.color_rgba = color_rgba; + rgb_to_gdkcolor(color_rgba, &gdkcolor); + gtk_widget_modify_text(ui.cur_item->widget, GTK_STATE_NORMAL, &gdkcolor); + gtk_widget_grab_focus(ui.cur_item->widget); +} + void process_color_activate(GtkMenuItem *menuitem, int color) { if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) { @@ -1277,6 +1362,10 @@ void process_color_activate(GtkMenuItem *menuitem, int color) } if (ui.cur_mapping != 0) return; // not user-generated + reset_focus(); + + if (ui.cur_item_type == ITEM_TEXT) + recolor_temp_text(color, predef_colors_rgba[color]); if (ui.selection != NULL) { recolor_selection(color); @@ -1284,8 +1373,10 @@ void process_color_activate(GtkMenuItem *menuitem, int color) update_color_menu(); } - if (ui.toolno[0] != TOOL_PEN && ui.toolno[0] != TOOL_HIGHLIGHTER) { + if (ui.toolno[0] != TOOL_PEN && ui.toolno[0] != TOOL_HIGHLIGHTER + && ui.toolno[0] != TOOL_TEXT) { if (ui.selection != NULL) return; + end_text(); ui.toolno[0] = TOOL_PEN; ui.cur_brush = &(ui.brushes[0][TOOL_PEN]); update_tool_buttons(); @@ -1311,6 +1402,7 @@ void process_thickness_activate(GtkMenuItem *menuitem, int tool, int val) if (ui.cur_mapping != 0) return; // not user-generated if (ui.selection != NULL && GTK_OBJECT_TYPE(menuitem) != GTK_TYPE_RADIO_MENU_ITEM) { + reset_focus(); rethicken_selection(val); update_thickness_buttons(); } @@ -1320,6 +1412,9 @@ void process_thickness_activate(GtkMenuItem *menuitem, int tool, int val) return; } + if (ui.brushes[0][tool].thickness_no == val) return; + reset_focus(); + end_text(); ui.brushes[0][tool].thickness_no = val; ui.brushes[0][tool].thickness = predef_thickness[tool][val]; update_mapping_linkings(tool); @@ -1440,6 +1535,15 @@ gboolean page_ops_forbidden(void) return (bgpdf.status != STATUS_NOT_INIT && bgpdf.create_pages); } +// send the focus back to the appropriate widget +void reset_focus(void) +{ + if (ui.cur_item_type == ITEM_TEXT) + gtk_widget_grab_focus(ui.cur_item->widget); + else + gtk_widget_grab_focus(GTK_WIDGET(canvas)); +} + // selection / clipboard stuff void reset_selection(void) @@ -1454,6 +1558,7 @@ void reset_selection(void) update_color_menu(); update_thickness_buttons(); update_color_buttons(); + update_font_button(); } void move_journal_items_by(GList *itemlist, double dx, double dy, @@ -1467,9 +1572,10 @@ void move_journal_items_by(GList *itemlist, double dx, double dy, while (itemlist!=NULL) { item = (struct Item *)itemlist->data; - if (item->type == ITEM_STROKE) { + if (item->type == ITEM_STROKE) for (pt=item->path->coords, i=0; i path->num_points; i++, pt+=2) { pt[0] += dx; pt[1] += dy; } + if (item->type == ITEM_STROKE || item->type == ITEM_TEXT || item->type == ITEM_TEMP_TEXT) { item->bbox.left += dx; item->bbox.right += dx; item->bbox.top += dy; @@ -1515,6 +1621,8 @@ void switch_mapping(int m) ui.cur_mapping = m; if (ui.toolno[m] < NUM_STROKE_TOOLS) ui.cur_brush = &(ui.brushes[m][ui.toolno[m]]); + if (ui.toolno[m] == TOOL_TEXT) + ui.cur_brush = &(ui.brushes[m][TOOL_PEN]); update_tool_buttons(); update_color_menu(); update_cursor(); @@ -1525,6 +1633,9 @@ void process_mapping_activate(GtkMenuItem *menuitem, int m, int tool) if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return; if (ui.cur_mapping!=0) return; if (ui.toolno[m] == tool) return; + end_text(); + reset_focus(); + ui.toolno[m] = tool; ui.ruler[m] = FALSE; if (ui.linked_brush[m] == BRUSH_LINKED @@ -1561,3 +1672,141 @@ void update_vbox_order(int *order) if (!present[i]) gtk_widget_hide(GET_COMPONENT(vbox_component_names[i])); } +gchar *make_cur_font_name(void) +{ + gchar *str; + struct Item *it; + + if (ui.cur_item_type == ITEM_TEXT) + str = g_strdup_printf("%s %.1f", ui.cur_item->font_name, ui.cur_item->font_size); + else if (ui.selection!=NULL && ui.selection->items!=NULL && + ui.selection->items->next==NULL && + (it=(struct Item*)ui.selection->items->data)->type == ITEM_TEXT) + str = g_strdup_printf("%s %.1f", it->font_name, it->font_size); + else + str = g_strdup_printf("%s %.1f", ui.font_name, ui.font_size); + return str; +} + +void update_font_button(void) +{ + gchar *str; + + str = make_cur_font_name(); + gtk_font_button_set_font_name(GTK_FONT_BUTTON(GET_COMPONENT("fontButton")), str); + g_free(str); +} + +gboolean can_accel(GtkWidget *widget, guint id, gpointer data) +{ + return GTK_WIDGET_SENSITIVE(widget); +} + +void allow_all_accels(void) +{ + g_signal_connect((gpointer) GET_COMPONENT("fileNew"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("fileOpen"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("fileSave"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("filePrint"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("filePrintPDF"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("fileQuit"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("editUndo"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("editRedo"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("editCut"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("editCopy"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("editPaste"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("editDelete"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("viewFullscreen"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("viewZoomIn"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("viewZoomOut"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("viewNormalSize"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("viewPageWidth"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("viewFirstPage"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("viewPreviousPage"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("viewNextPage"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("viewLastPage"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("toolsPen"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("toolsEraser"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("toolsHighlighter"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("toolsText"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); +/* g_signal_connect((gpointer) GET_COMPONENT("toolsSelectRegion"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); */ + g_signal_connect((gpointer) GET_COMPONENT("toolsSelectRectangle"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("toolsVerticalSpace"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("toolsHand"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("toolsTextFont"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); + g_signal_connect((gpointer) GET_COMPONENT("toolsRuler"), + "can-activate-accel", G_CALLBACK(can_accel), NULL); +} + +void add_scroll_bindings(void) +{ + GtkBindingSet *binding_set; + + binding_set = gtk_binding_set_by_class( + G_OBJECT_GET_CLASS(GET_COMPONENT("scrolledwindowMain"))); + gtk_binding_entry_add_signal(binding_set, GDK_Up, 0, + "scroll_child", 2, GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_BACKWARD, + G_TYPE_BOOLEAN, FALSE); + gtk_binding_entry_add_signal(binding_set, GDK_KP_Up, 0, + "scroll_child", 2, GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_BACKWARD, + G_TYPE_BOOLEAN, FALSE); + gtk_binding_entry_add_signal(binding_set, GDK_Down, 0, + "scroll_child", 2, GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_FORWARD, + G_TYPE_BOOLEAN, FALSE); + gtk_binding_entry_add_signal(binding_set, GDK_KP_Down, 0, + "scroll_child", 2, GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_FORWARD, + G_TYPE_BOOLEAN, FALSE); + gtk_binding_entry_add_signal(binding_set, GDK_Left, 0, + "scroll_child", 2, GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_BACKWARD, + G_TYPE_BOOLEAN, TRUE); + gtk_binding_entry_add_signal(binding_set, GDK_KP_Left, 0, + "scroll_child", 2, GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_BACKWARD, + G_TYPE_BOOLEAN, TRUE); + gtk_binding_entry_add_signal(binding_set, GDK_Right, 0, + "scroll_child", 2, GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_FORWARD, + G_TYPE_BOOLEAN, TRUE); + gtk_binding_entry_add_signal(binding_set, GDK_KP_Right, 0, + "scroll_child", 2, GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_FORWARD, + G_TYPE_BOOLEAN, TRUE); +} + +gboolean is_event_within_textview(GdkEventButton *event) +{ + double pt[2]; + + if (ui.cur_item_type!=ITEM_TEXT) return FALSE; + get_pointer_coords((GdkEvent *)event, pt); + if (pt[0] bbox.left || pt[0]>ui.cur_item->bbox.right) return FALSE; + if (pt[1] bbox.top || pt[1]>ui.cur_item->bbox.bottom) return FALSE; + return TRUE; +} diff --git a/src/xo-misc.h b/src/xo-misc.h index a82d371..e8f1d11 100644 --- a/src/xo-misc.h +++ b/src/xo-misc.h @@ -23,6 +23,7 @@ void fix_xinput_coords(GdkEvent *event); void update_item_bbox(struct Item *item); void make_page_clipbox(struct Page *pg); void make_canvas_items(void); +void make_canvas_item_one(GnomeCanvasGroup *group, struct Item *item); void update_canvas_bg(struct Page *pg); gboolean is_visible(struct Page *pg); void rescale_bg_pixmaps(void); @@ -30,6 +31,8 @@ void rescale_bg_pixmaps(void); gboolean have_intersect(struct BBox *a, struct BBox *b); void lower_canvas_item_to(GnomeCanvasGroup *g, GnomeCanvasItem *item, GnomeCanvasItem *after); +void rgb_to_gdkcolor(guint rgba, GdkColor *color); + // interface misc functions void update_thickness_buttons(void); @@ -50,9 +53,13 @@ void update_undo_redo_enabled(void); void update_copy_paste_enabled(void); void update_vbox_order(int *order); +gchar *make_cur_font_name(void); +void update_font_button(void); + void update_mapping_linkings(int toolno); void do_switch_page(int pg, gboolean rescroll, gboolean refresh_all); void set_cur_color(int color); +void recolor_temp_text(int color_no, guint color_rgba); void process_color_activate(GtkMenuItem *menuitem, int color); void process_thickness_activate(GtkMenuItem *menuitem, int tool, int val); void process_papercolor_activate(GtkMenuItem *menuitem, int color); @@ -61,6 +68,8 @@ void process_paperstyle_activate(GtkMenuItem *menuitem, int style); gboolean ok_to_close(void); gboolean page_ops_forbidden(void); +void reset_focus(void); + // selection / clipboard stuff void reset_selection(void); @@ -72,6 +81,12 @@ void move_journal_items_by(GList *itemlist, double dx, double dy, void switch_mapping(int m); void process_mapping_activate(GtkMenuItem *menuitem, int m, int tool); +// always allow accels +void allow_all_accels(void); +gboolean can_accel(GtkWidget *widget, guint id, gpointer data); +void add_scroll_bindings(void); + +gboolean is_event_within_textview(GdkEventButton *event); // defines for paper rulings diff --git a/src/xo-paint.c b/src/xo-paint.c index f52f124..dd03604 100644 --- a/src/xo-paint.c +++ b/src/xo-paint.c @@ -96,6 +96,9 @@ void update_cursor(void) else if (ui.toolno[ui.cur_mapping] == TOOL_HAND) { ui.cursor = gdk_cursor_new(GDK_HAND1); } + else if (ui.toolno[ui.cur_mapping] == TOOL_TEXT) { + ui.cursor = gdk_cursor_new(GDK_XTERM); + } gdk_window_set_cursor(GTK_WIDGET(canvas)->window, ui.cursor); } @@ -212,11 +215,7 @@ void finalize_stroke(void) // destroy the entire group of temporary line segments gtk_object_destroy(GTK_OBJECT(ui.cur_item->canvas_item)); // make a new line item to replace it - ui.cur_item->canvas_item = gnome_canvas_item_new(ui.cur_layer->group, - gnome_canvas_line_get_type(), "points", ui.cur_item->path, - "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND, - "fill-color-rgba", ui.cur_item->brush.color_rgba, - "width-units", ui.cur_item->brush.thickness, NULL); + make_canvas_item_one(ui.cur_layer->group, ui.cur_item); // add undo information prepare_new_undo(); @@ -292,11 +291,7 @@ void erase_stroke_portions(struct Item *item, double x, double y, double radius, // add the new head if (newhead != NULL) { update_item_bbox(newhead); - newhead->canvas_item = gnome_canvas_item_new(ui.cur_layer->group, - gnome_canvas_line_get_type(), "points", newhead->path, - "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND, - "fill-color-rgba", newhead->brush.color_rgba, - "width-units", newhead->brush.thickness, NULL); + make_canvas_item_one(ui.cur_layer->group, newhead); lower_canvas_item_to(ui.cur_layer->group, newhead->canvas_item, erasure->item->canvas_item); erasure->replacement_items = g_list_prepend(erasure->replacement_items, newhead); @@ -315,11 +310,7 @@ void erase_stroke_portions(struct Item *item, double x, double y, double radius, // add the tail if needed if (!need_recalc) return; update_item_bbox(item); - item->canvas_item = gnome_canvas_item_new(ui.cur_layer->group, - gnome_canvas_line_get_type(), "points", item->path, - "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND, - "fill-color-rgba", item->brush.color_rgba, - "width-units", item->brush.thickness, NULL); + make_canvas_item_one(ui.cur_layer->group, item); lower_canvas_item_to(ui.cur_layer->group, item->canvas_item, erasure->item->canvas_item); } @@ -463,10 +454,23 @@ void finalize_selectrect(void) } } + if (ui.selection->items == NULL) { + // if we clicked inside a text zone ? + item = click_is_in_text(ui.selection->layer, x1, y1); + if (item!=NULL && item==click_is_in_text(ui.selection->layer, x2, y2)) { + ui.selection->items = g_list_append(ui.selection->items, item); + g_memmove(&(ui.selection->bbox), &(item->bbox), sizeof(struct BBox)); + gnome_canvas_item_set(ui.selection->canvas_item, + "x1", item->bbox.left, "x2", item->bbox.right, + "y1", item->bbox.top, "y2", item->bbox.bottom, NULL); + } + } + if (ui.selection->items == NULL) reset_selection(); else make_dashed(ui.selection->canvas_item); update_cursor(); update_copy_paste_enabled(); + update_font_button(); } gboolean start_movesel(GdkEvent *event) @@ -702,7 +706,7 @@ void callback_clipboard_clear(GtkClipboard *clipboard, gpointer user_data) void selection_to_clip(void) { - int bufsz, nitems; + int bufsz, nitems, val; char *buf, *p; GList *list; struct Item *item; @@ -721,6 +725,16 @@ void selection_to_clip(void) + sizeof(int) // num_points + 2*item->path->num_points*sizeof(double); // the points } + else if (item->type == ITEM_TEXT) { + bufsz+= sizeof(int) // type + + sizeof(struct Brush) // brush + + 2*sizeof(double) // bbox upper-left + + sizeof(int) // text len + + strlen(item->text)+1 // text + + sizeof(int) // font_name len + + strlen(item->font_name)+1 // font_name + + sizeof(double); // font_size + } else bufsz+= sizeof(int); // type } p = buf = g_malloc(bufsz); @@ -736,6 +750,18 @@ void selection_to_clip(void) g_memmove(p, item->path->coords, 2*item->path->num_points*sizeof(double)); p+= 2*item->path->num_points*sizeof(double); } + if (item->type == ITEM_TEXT) { + g_memmove(p, &item->brush, sizeof(struct Brush)); p+= sizeof(struct Brush); + g_memmove(p, &item->bbox.left, sizeof(double)); p+= sizeof(double); + g_memmove(p, &item->bbox.top, sizeof(double)); p+= sizeof(double); + val = strlen(item->text); + g_memmove(p, &val, sizeof(int)); p+= sizeof(int); + g_memmove(p, item->text, val+1); p+= val+1; + val = strlen(item->font_name); + g_memmove(p, &val, sizeof(int)); p+= sizeof(int); + g_memmove(p, item->font_name, val+1); p+= val+1; + g_memmove(p, &item->font_size, sizeof(double)); p+= sizeof(double); + } } target.target = "_XOURNAL"; @@ -752,7 +778,7 @@ void clipboard_paste(void) { GtkSelectionData *sel_data; unsigned char *p; - int nitems, npts, i; + int nitems, npts, i, len; GList *list; struct Item *item; double hoffset, voffset, cx, cy; @@ -824,11 +850,22 @@ void clipboard_paste(void) } p+= 2*item->path->num_points*sizeof(double); update_item_bbox(item); - item->canvas_item = gnome_canvas_item_new(ui.cur_layer->group, - gnome_canvas_line_get_type(), "points", item->path, - "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND, - "fill-color-rgba", item->brush.color_rgba, - "width-units", item->brush.thickness, NULL); + make_canvas_item_one(ui.cur_layer->group, item); + } + if (item->type == ITEM_TEXT) { + g_memmove(&item->brush, p, sizeof(struct Brush)); p+= sizeof(struct Brush); + g_memmove(&item->bbox.left, p, sizeof(double)); p+= sizeof(double); + g_memmove(&item->bbox.top, p, sizeof(double)); p+= sizeof(double); + item->bbox.left += hoffset; + item->bbox.top += voffset; + g_memmove(&len, p, sizeof(int)); p+= sizeof(int); + item->text = g_malloc(len+1); + g_memmove(item->text, p, len+1); p+= len+1; + g_memmove(&len, p, sizeof(int)); p+= sizeof(int); + item->font_name = g_malloc(len+1); + g_memmove(item->font_name, p, len+1); p+= len+1; + g_memmove(&item->font_size, p, sizeof(double)); p+= sizeof(double); + make_canvas_item_one(ui.cur_layer->group, item); } } @@ -856,7 +893,8 @@ void recolor_selection(int color) undo->auxlist = NULL; for (itemlist = ui.selection->items; itemlist!=NULL; itemlist = itemlist->next) { item = (struct Item *)itemlist->data; - if (item->type != ITEM_STROKE || item->brush.tool_type!=TOOL_PEN) continue; + if (item->type != ITEM_STROKE && item->type != ITEM_TEXT) continue; + if (item->type == ITEM_STROKE && item->brush.tool_type!=TOOL_PEN) continue; // store info for undo undo->itemlist = g_list_append(undo->itemlist, item); brush = (struct Brush *)g_malloc(sizeof(struct Brush)); @@ -899,14 +937,276 @@ void rethicken_selection(int val) } } +gboolean do_hand_scrollto(gpointer data) +{ + ui.hand_scrollto_pending = FALSE; + gnome_canvas_scroll_to(canvas, ui.hand_scrollto_cx, ui.hand_scrollto_cy); + return FALSE; +} + void do_hand(GdkEvent *event) { - double pt[2], val; + double pt[2]; int cx, cy; get_pointer_coords(event, pt); gnome_canvas_get_scroll_offsets(canvas, &cx, &cy); - cx -= (pt[0]-ui.hand_refpt[0])*ui.zoom; - cy -= (pt[1]-ui.hand_refpt[1])*ui.zoom; - gnome_canvas_scroll_to(canvas, cx, cy); + ui.hand_scrollto_cx = cx - (pt[0]-ui.hand_refpt[0])*ui.zoom; + ui.hand_scrollto_cy = cy - (pt[1]-ui.hand_refpt[1])*ui.zoom; + if (!ui.hand_scrollto_pending) g_idle_add(do_hand_scrollto, NULL); + ui.hand_scrollto_pending = TRUE; +} + +/************ TEXT FUNCTIONS **************/ + +// to make it easier to copy/paste at end of text box +#define WIDGET_RIGHT_MARGIN 10 + +void resize_textview(gpointer *toplevel, gpointer *data) +{ + GtkTextView *w; + int width, height; + + /* when the text changes, resize the GtkTextView accordingly */ + if (ui.cur_item_type!=ITEM_TEXT) return; + w = GTK_TEXT_VIEW(ui.cur_item->widget); + width = w->width + WIDGET_RIGHT_MARGIN; + height = w->height; + gnome_canvas_item_set(ui.cur_item->canvas_item, + "size-pixels", TRUE, + "width", (gdouble)width, "height", (gdouble)height, NULL); + ui.cur_item->bbox.right = ui.cur_item->bbox.left + width/ui.zoom; + ui.cur_item->bbox.bottom = ui.cur_item->bbox.top + height/ui.zoom; +} + +void start_text(GdkEvent *event, struct Item *item) +{ + double pt[2]; + gchar *text; + GtkTextBuffer *buffer; + GnomeCanvasItem *canvas_item; + PangoFontDescription *font_desc; + GdkColor color; + + get_pointer_coords(event, pt); + ui.cur_item_type = ITEM_TEXT; + + if (item==NULL) { + item = g_new(struct Item, 1); + item->text = NULL; + item->canvas_item = NULL; + item->bbox.left = pt[0]; + item->bbox.top = pt[1]; + item->bbox.right = ui.cur_page->width; + item->bbox.bottom = pt[1]+100.; + item->font_name = g_strdup(ui.font_name); + item->font_size = ui.font_size; + g_memmove(&(item->brush), ui.cur_brush, sizeof(struct Brush)); + ui.cur_layer->items = g_list_append(ui.cur_layer->items, item); + ui.cur_layer->nitems++; + } + + item->type = ITEM_TEMP_TEXT; + ui.cur_item = item; + + font_desc = pango_font_description_from_string(item->font_name); + pango_font_description_set_absolute_size(font_desc, + item->font_size*ui.zoom*PANGO_SCALE); + item->widget = gtk_text_view_new(); + buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(item->widget)); + if (item->text!=NULL) + gtk_text_buffer_set_text(buffer, item->text, -1); + gtk_widget_modify_font(item->widget, font_desc); + rgb_to_gdkcolor(item->brush.color_rgba, &color); + gtk_widget_modify_text(item->widget, GTK_STATE_NORMAL, &color); + pango_font_description_free(font_desc); + + canvas_item = gnome_canvas_item_new(ui.cur_layer->group, + gnome_canvas_widget_get_type(), + "x", item->bbox.left, "y", item->bbox.top, + "width", item->bbox.right-item->bbox.left, + "height", item->bbox.bottom-item->bbox.top, + "widget", item->widget, NULL); + // TODO: width/height? + if (item->canvas_item!=NULL) { + lower_canvas_item_to(ui.cur_layer->group, canvas_item, item->canvas_item); + gtk_object_destroy(GTK_OBJECT(item->canvas_item)); + } + item->canvas_item = canvas_item; + + gtk_widget_show(item->widget); + gtk_widget_grab_focus(item->widget); + ui.resize_signal_handler = + g_signal_connect((gpointer) winMain, "check_resize", + G_CALLBACK(resize_textview), NULL); + update_font_button(); + gtk_widget_set_sensitive(GET_COMPONENT("editPaste"), FALSE); + gtk_widget_set_sensitive(GET_COMPONENT("buttonPaste"), FALSE); +} + +void end_text(void) +{ + GtkTextBuffer *buffer; + GtkTextIter start, end; + gchar *new_text; + struct UndoErasureData *erasure; + GnomeCanvasItem *tmpitem; + + if (ui.cur_item_type!=ITEM_TEXT) return; // nothing for us to do! + + // finalize the text that's been edited... + buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ui.cur_item->widget)); + gtk_text_buffer_get_bounds(buffer, &start, &end); + ui.cur_item->type = ITEM_TEXT; + new_text = gtk_text_buffer_get_text(buffer, &start, &end, TRUE); + ui.cur_item_type = ITEM_NONE; + gtk_widget_set_sensitive(GET_COMPONENT("editPaste"), TRUE); + gtk_widget_set_sensitive(GET_COMPONENT("buttonPaste"), TRUE); + + if (strlen(new_text)==0) { // erase object and cancel + g_free(new_text); + g_signal_handler_disconnect(winMain, ui.resize_signal_handler); + gtk_object_destroy(GTK_OBJECT(ui.cur_item->canvas_item)); + ui.cur_item->canvas_item = NULL; + if (ui.cur_item->text == NULL) // nothing happened + g_free(ui.cur_item->font_name); + else { // treat this as an erasure + prepare_new_undo(); + undo->type = ITEM_ERASURE; + undo->layer = ui.cur_layer; + erasure = (struct UndoErasureData *)g_malloc(sizeof(struct UndoErasureData)); + erasure->item = ui.cur_item; + erasure->npos = g_list_index(ui.cur_layer->items, ui.cur_item); + erasure->nrepl = 0; + erasure->replacement_items = NULL; + undo->erasurelist = g_list_append(NULL, erasure); + } + ui.cur_layer->items = g_list_remove(ui.cur_layer->items, ui.cur_item); + ui.cur_layer->nitems--; + ui.cur_item = NULL; + return; + } + + // store undo data + if (ui.cur_item->text==NULL || strcmp(ui.cur_item->text, new_text)) { + prepare_new_undo(); + if (ui.cur_item->text == NULL) undo->type = ITEM_TEXT; + else undo->type = ITEM_TEXT_EDIT; + undo->layer = ui.cur_layer; + undo->item = ui.cur_item; + undo->str = ui.cur_item->text; + } + else g_free(ui.cur_item->text); + + ui.cur_item->text = new_text; + ui.cur_item->widget = NULL; + // replace the canvas item + tmpitem = ui.cur_item->canvas_item; + make_canvas_item_one(ui.cur_layer->group, ui.cur_item); + update_item_bbox(ui.cur_item); + lower_canvas_item_to(ui.cur_layer->group, ui.cur_item->canvas_item, tmpitem); + gtk_object_destroy(GTK_OBJECT(tmpitem)); +} + +/* update the items in the canvas so they're of the right font size */ + +void update_text_item_displayfont(struct Item *item) +{ + PangoFontDescription *font_desc; + + if (item->type != ITEM_TEXT && item->type != ITEM_TEMP_TEXT) return; + if (item->canvas_item==NULL) return; + font_desc = pango_font_description_from_string(item->font_name); + pango_font_description_set_absolute_size(font_desc, + item->font_size*ui.zoom*PANGO_SCALE); + if (item->type == ITEM_TEMP_TEXT) + gtk_widget_modify_font(item->widget, font_desc); + else { + gnome_canvas_item_set(item->canvas_item, "font-desc", font_desc, NULL); + update_item_bbox(item); + } + pango_font_description_free(font_desc); +} + +void rescale_text_items(void) +{ + GList *pagelist, *layerlist, *itemlist; + struct Layer *l; + + for (pagelist = journal.pages; pagelist!=NULL; pagelist = pagelist->next) + for (layerlist = ((struct Page *)pagelist->data)->layers; layerlist!=NULL; layerlist = layerlist->next) + for (itemlist = ((struct Layer *)layerlist->data)->items; itemlist!=NULL; itemlist = itemlist->next) + update_text_item_displayfont((struct Item *)itemlist->data); +} + +struct Item *click_is_in_text(struct Layer *layer, double x, double y) +{ + GList *itemlist; + struct Item *item, *val; + + val = NULL; + for (itemlist = layer->items; itemlist!=NULL; itemlist = itemlist->next) { + item = (struct Item *)itemlist->data; + if (item->type != ITEM_TEXT) continue; + if (x bbox.left || x>item->bbox.right) continue; + if (y bbox.top || y>item->bbox.bottom) continue; + val = item; + } + return val; +} + +void refont_text_item(struct Item *item, gchar *font_name, double font_size) +{ + if (!strcmp(font_name, item->font_name) && font_size==item->font_size) return; + if (item->text!=NULL) { + prepare_new_undo(); + undo->type = ITEM_TEXT_ATTRIB; + undo->item = item; + undo->str = item->font_name; + undo->val_x = item->font_size; + undo->brush = (struct Brush *)g_memdup(&(item->brush), sizeof(struct Brush)); + } + else g_free(item->font_name); + item->font_name = g_strdup(font_name); + if (font_size>0.) item->font_size = font_size; + update_text_item_displayfont(item); +} + +void process_font_sel(gchar *str) +{ + gchar *p, *q; + struct Item *it; + gdouble size; + GList *list; + gboolean undo_cont; + + p = strrchr(str, ' '); + if (p!=NULL) { + size = g_strtod(p+1, &q); + if (*q!=0 || size<1.) size=0.; + else *p=0; + } + else size=0.; + reset_focus(); + g_free(ui.font_name); + ui.font_name = str; + if (size>0.) ui.font_size = size; + undo_cont = FALSE; + // if there's a current text item, re-font it + if (ui.cur_item_type == ITEM_TEXT) { + refont_text_item(ui.cur_item, str, size); + undo_cont = (ui.cur_item->text!=NULL); + } + // if there's a current selection, re-font it + if (ui.selection!=NULL) + for (list=ui.selection->items; list!=NULL; list=list->next) { + it = (struct Item *)list->data; + if (it->type == ITEM_TEXT) { + if (undo_cont) undo->multiop |= MULTIOP_CONT_REDO; + refont_text_item(it, str, size); + if (undo_cont) undo->multiop |= MULTIOP_CONT_UNDO; + undo_cont = TRUE; + } + } + update_font_button(); } diff --git a/src/xo-paint.h b/src/xo-paint.h index d01cee2..4799a7e 100644 --- a/src/xo-paint.h +++ b/src/xo-paint.h @@ -22,3 +22,16 @@ void clipboard_paste(void); void recolor_selection(int color); void rethicken_selection(int val); + +/* text functions */ + +#define DEFAULT_FONT "Sans" +#define DEFAULT_FONT_SIZE 12 + +void start_text(GdkEvent *event, struct Item *item); +void end_text(void); +void update_text_item_displayfont(struct Item *item); +void rescale_text_items(void); +struct Item *click_is_in_text(struct Layer *layer, double x, double y); +void refont_text_item(struct Item *item, gchar *font_name, double font_size); +void process_font_sel(gchar *str); diff --git a/src/xo-print.c b/src/xo-print.c index cc2d4c1..cfd61e1 100644 --- a/src/xo-print.c +++ b/src/xo-print.c @@ -2,12 +2,21 @@ # include #endif +#define PANGO_ENABLE_BACKEND /* to access PangoFcFont.font_pattern */ + #include #include #include +#include #include #include #include +#include +#include +#include +#include +#include FT_FREETYPE_H +#include "sft.h" /* Sun Font Tools, embedded in libgnomeprint */ #include "xournal.h" #include "xo-misc.h" @@ -531,8 +540,9 @@ GString *make_pdfprefix(struct PdfPageDesc *pgdesc, double width, double height) GString *str; double v[4], t, xscl, yscl; int i; - - str = g_string_new("q "); + + // push 3 times in case code to be annotated has unbalanced q/Q (B of A., ...) + str = g_string_new("q q q "); if (pgdesc->rotate == 90) { g_string_append_printf(str, "0 -1 1 0 0 %.2f cm ", height); t = height; height = width; width = t; @@ -752,20 +762,278 @@ int pdf_draw_bitmap_background(struct Page *pg, GString *str, return xref->last; } +// manipulate Pdf fonts + +struct PdfFont *new_pdffont(struct XrefTable *xref, GList **fonts, + unsigned char *filename, int font_id, FT_Face face, int glyph_page) +{ + GList *list; + struct PdfFont *font; + int i; + const char *s; + + for (list = *fonts; list!=NULL; list = list->next) { + font = (struct PdfFont *)list->data; + if (!strcmp(font->filename, filename) && font->font_id == font_id + && font->glyph_page == glyph_page) + { font->used_in_this_page = TRUE; return font; } + } + font = g_malloc(sizeof(struct PdfFont)); + *fonts = g_list_append(*fonts, font); + font->n_obj = xref->last+1; + make_xref(xref, xref->last+1, 0); // will give it a value later + font->filename = g_strdup(filename); + font->font_id = font_id; + font->glyph_page = glyph_page; + font->used_in_this_page = TRUE; + font->num_glyphs_used = 0; + for (i=0; i<256; i++) { + font->glyphmap[i] = -1; + font->advance[i] = 0; + font->glyphpsnames[i] = NULL; + } + font->glyphmap[0] = 0; + // fill in info from the FT_Face + font->is_truetype = FT_IS_SFNT(face); + font->nglyphs = face->num_glyphs; + font->ft2ps = 1000.0 / face->units_per_EM; + font->ascender = (int)(font->ft2ps*face->ascender); + font->descender = (int)(font->ft2ps*face->descender); + if (face->bbox.xMin < -100000 || face->bbox.xMin > 100000) font->xmin = 0; + else font->xmin = (int)(font->ft2ps*face->bbox.xMin); + if (face->bbox.xMax < -100000 || face->bbox.xMax > 100000) font->xmax = 0; + else font->xmax = (int)(font->ft2ps*face->bbox.xMax); + if (face->bbox.yMin < -100000 || face->bbox.yMin > 100000) font->ymin = 0; + else font->ymin = (int)(font->ft2ps*face->bbox.yMin); + if (face->bbox.yMax < -100000 || face->bbox.yMax > 100000) font->ymax = 0; + else font->ymax = (int)(font->ft2ps*face->bbox.yMax); + if (font->is_truetype) font->flags = 4; // symbolic + else { + font->flags = 4; // symbolic + if (FT_IS_FIXED_WIDTH(face)) font->flags |= 1; + if (face->style_flags & FT_STYLE_FLAG_ITALIC) font->flags |= 64; + } + s = FT_Get_Postscript_Name(face); + if (s==NULL) s = "Noname"; + if (glyph_page) font->fontname = g_strdup_printf("%s_%03d", s, glyph_page); + else font->fontname = g_strdup(s); + return font; +} + +#define pfb_get_length(x) (((x)[3]<<24) + ((x)[2]<<16) + ((x)[1]<<8) + (x)[0]) +#define T1_SEGMENT_1_END "currentfile eexec" +#define T1_SEGMENT_3_END "cleartomark" + +void embed_pdffont(GString *pdfbuf, struct XrefTable *xref, struct PdfFont *font) +{ + // this code inspired by libgnomeprint + gboolean fallback, is_binary; + guchar encoding[256]; + gushort glyphs[256]; + int i, j, num, len, len1, len2; + TrueTypeFont *ttfnt; + char *tmpfile, *seg1, *seg2; + unsigned char *fontdata, *p; + char prefix[8]; + int nobj_fontprog, nobj_descr, lastchar; + + fallback = FALSE; + // embed the font file: TrueType case + if (font->is_truetype) { + glyphs[0] = encoding[0] = 0; + num = 1; + for (i=1; i<=255; i++) + if (font->glyphmap[i]>=0) { + font->glyphmap[i] = num; + glyphs[num] = 255*font->glyph_page+i-1; + encoding[num] = i; + num++; + } + font->num_glyphs_used = num-1; + if (OpenTTFont(font->filename, 0, &ttfnt) == SF_OK) { + tmpfile = mktemp(g_strdup(TMPDIR_TEMPLATE)); + CreateTTFromTTGlyphs(ttfnt, tmpfile, glyphs, encoding, num, + 0, NULL, TTCF_AutoName | TTCF_IncludeOS2); + CloseTTFont(ttfnt); + if (g_file_get_contents(tmpfile, (char **)&fontdata, &len, NULL) && len>=8) { + make_xref(xref, xref->last+1, pdfbuf->len); + nobj_fontprog = xref->last; + g_string_append_printf(pdfbuf, + "%d 0 obj\n<< /Length %d /Length1 %d >> stream\n", + nobj_fontprog, len, len); + g_string_append_len(pdfbuf, fontdata, len); + g_string_append(pdfbuf, "endstream\nendobj\n"); + g_free(fontdata); + } + else fallback = TRUE; + unlink(tmpfile); + g_free(tmpfile); + } + else fallback = TRUE; + } else { + // embed the font file: Type1 case + if (g_file_get_contents(font->filename, (char **)&fontdata, &len, NULL) && len>=8) { + if (fontdata[0]==0x80 && fontdata[1]==0x01) { + is_binary = TRUE; + len1 = pfb_get_length(fontdata+2); + if (fontdata[len1+6]!=0x80 || fontdata[len1+7]!=0x02) fallback = TRUE; + else { + len2 = pfb_get_length(fontdata+len1+8); + if (fontdata[len1+len2+12]!=0x80 || fontdata[len1+len2+13]!=0x01) + fallback = TRUE; + } + } + else if (!strncmp(fontdata, "%!PS", 4)) { + is_binary = FALSE; + p = strstr(fontdata, T1_SEGMENT_1_END) + strlen(T1_SEGMENT_1_END); + if (p==NULL) fallback = TRUE; + else { + if (*p=='\n' || *p=='\r') p++; + if (*p=='\n' || *p=='\r') p++; + len1 = p-fontdata; + p = g_strrstr_len(fontdata, len, T1_SEGMENT_3_END); + if (p==NULL) fallback = TRUE; + else { + // rewind 512 zeros + i = 512; p--; + while (i>0 && p!=fontdata && (*p=='0' || *p=='\r' || *p=='\n')) { + if (*p=='0') i--; + p--; + } + while (p!=fontdata && (*p=='\r' || *p=='\n')) p--; + p++; + if (i>0) fallback = TRUE; + else len2 = p-fontdata-len1; + } + } + } + else fallback = TRUE; + if (!fallback) { + if (is_binary) { + seg1 = fontdata+6; + seg2 = fontdata + len1 + 12; + } else { + seg1 = fontdata; + seg2 = g_malloc(len2/2); + j=0; + p = fontdata+len1; + while (p+1 < fontdata+len1+len2) { + if (*p==' '||*p=='\t'||*p=='\n'||*p=='\r') { p++; continue; } + if (p[0]>'9') { p[0]|=0x20; p[0]-=39; } + if (p[1]>'9') { p[1]|=0x20; p[1]-=39; } + seg2[j++] = ((p[0]-'0')<<4) + (p[1]-'0'); + p+=2; + } + len2 = j; + } + make_xref(xref, xref->last+1, pdfbuf->len); + nobj_fontprog = xref->last; + g_string_append_printf(pdfbuf, + "%d 0 obj\n<< /Length %d /Length1 %d /Length2 %d /Length3 0 >> stream\n", + nobj_fontprog, len1+len2, len1, len2); + g_string_append_len(pdfbuf, seg1, len1); + g_string_append_len(pdfbuf, seg2, len2); + g_string_append(pdfbuf, "endstream\nendobj\n"); + if (!is_binary) g_free(seg2); + } + g_free(fontdata); + } + else fallback = TRUE; + } + + // next, the font descriptor + if (!fallback) { + make_xref(xref, xref->last+1, pdfbuf->len); + nobj_descr = xref->last; + g_string_append_printf(pdfbuf, + "%d 0 obj\n<< /Type /FontDescriptor /FontName /%s /Flags %d " + "/FontBBox [%d %d %d %d] /ItalicAngle 0 /Ascent %d " + "/Descent %d /CapHeight %d /StemV 100 /%s %d 0 R >> endobj\n", + nobj_descr, font->fontname, font->flags, + font->xmin, font->ymin, font->xmax, font->ymax, + font->ascender, -font->descender, font->ascender, + font->is_truetype ? "FontFile2":"FontFile", + nobj_fontprog); + } + + // finally, the font itself + /* Note: in Type1 case, font->glyphmap maps charcodes to glyph no's + in TrueType case, encoding lists the used charcodes by index, + glyphs list the used glyph no's by index + font->glyphmap maps charcodes to indices */ + xref->data[font->n_obj] = pdfbuf->len; + if (font->is_truetype) lastchar = encoding[font->num_glyphs_used]; + else lastchar = font->num_glyphs_used; + if (fallback) { + font->is_truetype = FALSE; + g_free(font->fontname); + font->fontname = g_strdup("Helvetica"); + } + prefix[0]=0; + if (font->is_truetype) { + num = font->glyph_page; + for (i=0; i<6; i++) { prefix[i] = 'A'+(num%26); num/=26; } + prefix[6]='+'; prefix[7]=0; + } + g_string_append_printf(pdfbuf, + "%d 0 obj\n<< /Type /Font /Subtype /%s /BaseFont /%s%s /Name /F%d ", + font->n_obj, font->is_truetype?"TrueType":"Type1", + prefix, font->fontname, font->n_obj); + if (!fallback) { + g_string_append_printf(pdfbuf, + "/FontDescriptor %d 0 R /FirstChar 0 /LastChar %d /Widths [", + nobj_descr, lastchar); + for (i=0; i<=lastchar; i++) + g_string_append_printf(pdfbuf, "%d ", font->advance[i]); + g_string_append(pdfbuf, "] "); + } + if (!font->is_truetype) { /* encoding */ + g_string_append(pdfbuf, "/Encoding << /Type /Encoding " + "/BaseEncoding /MacRomanEncoding /Differences [1 "); + for (i=1; i<=lastchar; i++) { + g_string_append_printf(pdfbuf, "/%s ", font->glyphpsnames[i]); + g_free(font->glyphpsnames[i]); + } + g_string_append(pdfbuf, "] >> "); + } + g_string_append(pdfbuf, ">> endobj\n"); +} + // draw a page's graphics -void pdf_draw_page(struct Page *pg, GString *str, gboolean *use_hiliter) +void pdf_draw_page(struct Page *pg, GString *str, gboolean *use_hiliter, + struct XrefTable *xref, GList **pdffonts) { - GList *layerlist, *itemlist; + GList *layerlist, *itemlist, *tmplist; struct Layer *l; struct Item *item; - guint old_rgba; + guint old_rgba, old_text_rgba; double old_thickness; double *pt; - int i; + int i, j; + PangoFontDescription *font_desc; + PangoContext *context; + PangoLayout *layout; + PangoLayoutIter *iter; + PangoRectangle logical_rect; + PangoLayoutRun *run; + PangoFcFont *fcfont; + FcPattern *pattern; + int baseline, advance; + int glyph_no, glyph_page, current_page; + unsigned char *filename; + char tmpstr[200]; + int font_id; + FT_Face ftface; + struct PdfFont *cur_font; + gboolean in_string; - old_rgba = 0x12345678; // not any values we use, so we'll reset them + old_rgba = old_text_rgba = 0x12345678; // not any values we use, so we'll reset them old_thickness = 0.0; + for (tmplist = *pdffonts; tmplist!=NULL; tmplist = tmplist->next) { + cur_font = (struct PdfFont *)tmplist->data; + cur_font->used_in_this_page = FALSE; + } for (layerlist = pg->layers; layerlist!=NULL; layerlist = layerlist->next) { l = (struct Layer *)layerlist->data; @@ -791,6 +1059,88 @@ void pdf_draw_page(struct Page *pg, GString *str, gboolean *use_hiliter) if ((item->brush.color_rgba & 0xf0) != 0xf0) // undo transparent g_string_append(str, "Q "); } + else if (item->type == ITEM_TEXT) { + if ((item->brush.color_rgba & ~0xff) != old_text_rgba) + g_string_append_printf(str, "%.2f %.2f %.2f rg ", + RGBA_RGB(item->brush.color_rgba)); + old_text_rgba = item->brush.color_rgba & ~0xff; + context = gnome_print_pango_create_context(gnome_print_pango_get_default_font_map()); + layout = pango_layout_new(context); + g_object_unref(context); + font_desc = pango_font_description_from_string(item->font_name); + pango_font_description_set_absolute_size(font_desc, + item->font_size*PANGO_SCALE); + pango_layout_set_font_description(layout, font_desc); + pango_font_description_free(font_desc); + pango_layout_set_text(layout, item->text, -1); + // this code inspired by the code in libgnomeprint + iter = pango_layout_get_iter(layout); + do { + run = pango_layout_iter_get_run(iter); + if (run==NULL) continue; + pango_layout_iter_get_run_extents (iter, NULL, &logical_rect); + baseline = pango_layout_iter_get_baseline (iter); + if (!PANGO_IS_FC_FONT(run->item->analysis.font)) continue; + fcfont = PANGO_FC_FONT(run->item->analysis.font); + pattern = fcfont->font_pattern; + if (FcPatternGetString(pattern, FC_FILE, 0, &filename) != FcResultMatch || + FcPatternGetInteger(pattern, FC_INDEX, 0, &font_id) != FcResultMatch) + continue; + ftface = pango_fc_font_lock_face(fcfont); + current_page = -1; + cur_font = NULL; + g_string_append_printf(str, "BT %.2f 0 0 %.2f %.2f %.2f Tm ", + item->font_size, -item->font_size, + item->bbox.left + (gdouble) logical_rect.x/PANGO_SCALE, + item->bbox.top + (gdouble) baseline/PANGO_SCALE); + in_string = FALSE; + for (i=0; i glyphs->num_glyphs; i++) { + glyph_no = run->glyphs->glyphs[i].glyph; + if (FT_IS_SFNT(ftface)) glyph_page = glyph_no/255; + else glyph_page = 0; + if (glyph_page != current_page) { + cur_font = new_pdffont(xref, pdffonts, filename, font_id, + ftface, glyph_page); + if (in_string) g_string_append(str, ") Tj "); + in_string = FALSE; + g_string_append_printf(str, "/F%d 1 Tf ", cur_font->n_obj); + } + current_page = glyph_page; + FT_Load_Glyph(ftface, glyph_no, FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM); + advance = (int)(ftface->glyph->metrics.horiAdvance * cur_font->ft2ps + 0.5); + if (!in_string) g_string_append_c(str, '('); + in_string = TRUE; + if (cur_font->is_truetype) { + if (glyph_no) glyph_no = (glyph_no%255)+1; + cur_font->glyphmap[glyph_no] = glyph_no; + } + else { + for (j=1; j<=cur_font->num_glyphs_used; j++) + if (cur_font->glyphmap[j] == glyph_no) break; + if (j==256) j=0; // font is full, what do we do? + if (j>cur_font->num_glyphs_used) { + cur_font->glyphmap[j] = glyph_no; + cur_font->num_glyphs_used++; + if (FT_Get_Glyph_Name(ftface, glyph_no, tmpstr, 200) == FT_Err_Ok) + cur_font->glyphpsnames[j] = g_strdup(tmpstr); + else cur_font->glyphpsnames[j] = g_strdup(".notdef"); + } + glyph_no = j; + } + cur_font->advance[glyph_no] = advance; + if (glyph_no=='\\' || glyph_no == '(' || glyph_no == ')' || glyph_no == 10 || glyph_no == 13) + g_string_append_c(str, '\\'); + if (glyph_no==10) g_string_append_c(str,'n'); + else if (glyph_no==13) g_string_append_c(str,'r'); + else g_string_append_c(str, glyph_no); + } + if (in_string) g_string_append(str, ") Tj "); + g_string_append(str, "ET "); + pango_fc_font_unlock_face(fcfont); + } while (pango_layout_iter_next_run(iter)); + pango_layout_iter_free(iter); + g_object_unref(layout); + } } } } @@ -819,6 +1169,9 @@ gboolean print_to_pdf(char *filename) gboolean use_hiliter; struct PdfInfo pdfinfo; struct PdfObj *obj; + GList *pdffonts, *list; + struct PdfFont *font; + char *tmpbuf; f = fopen(filename, "w"); if (f == NULL) return FALSE; @@ -826,6 +1179,7 @@ gboolean print_to_pdf(char *filename) annot = FALSE; xref.data = NULL; uses_pdf = FALSE; + pdffonts = NULL; for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) { pg = (struct Page *)pglist->data; if (pg->bg->type == BG_PDF) uses_pdf = TRUE; @@ -866,8 +1220,8 @@ gboolean print_to_pdf(char *filename) g_string_append_printf(pdfbuf, "] /Count %d >> endobj\n", journal.npages); make_xref(&xref, n_obj_catalog+2, pdfbuf->len); g_string_append_printf(pdfbuf, - "%d 0 obj\n<< /Type /ExtGState /CA 0.5 >> endobj\n", - n_obj_catalog+2); + "%d 0 obj\n<< /Type /ExtGState /CA %.2f >> endobj\n", + n_obj_catalog+2, ui.hiliter_opacity); xref.last = n_obj_pages_offs + journal.npages-1; for (pglist = journal.pages, n_page = 0; pglist!=NULL; @@ -891,13 +1245,13 @@ gboolean print_to_pdf(char *filename) "%d 0 obj\n<< /Length %d >> stream\n%s\nendstream\nendobj\n", n_obj_prefix, tmpstr->len, tmpstr->str); g_string_free(tmpstr, TRUE); - g_string_prepend(pgstrm, "Q "); + g_string_prepend(pgstrm, "Q Q Q "); } else if (pg->bg->type == BG_PIXMAP || pg->bg->type == BG_PDF) n_obj_bgpix = pdf_draw_bitmap_background(pg, pgstrm, &xref, pdfbuf); // draw the page contents use_hiliter = FALSE; - pdf_draw_page(pg, pgstrm, &use_hiliter); + pdf_draw_page(pg, pgstrm, &use_hiliter, &xref, &pdffonts); g_string_append_printf(pgstrm, "Q\n"); // deflate pgstrm and write it @@ -962,11 +1316,32 @@ gboolean print_to_pdf(char *filename) if (n_obj_bgpix>0) add_dict_subentry(pdfbuf, &xref, obj, "/XObject", PDFTYPE_DICT, "/ImBg", mk_pdfref(n_obj_bgpix)); + for (list=pdffonts; list!=NULL; list = list->next) { + font = (struct PdfFont *)list->data; + if (font->used_in_this_page) { + add_dict_subentry(pdfbuf, &xref, + obj, "/ProcSet", PDFTYPE_ARRAY, NULL, mk_pdfname("/Text")); + tmpbuf = g_strdup_printf("/F%d", font->n_obj); + add_dict_subentry(pdfbuf, &xref, + obj, "/Font", PDFTYPE_DICT, tmpbuf, mk_pdfref(font->n_obj)); + g_free(tmpbuf); + } + } show_pdfobj(obj, pdfbuf); free_pdfobj(obj); g_string_append(pdfbuf, " >> endobj\n"); } + // after the pages, we insert fonts + for (list = pdffonts; list!=NULL; list = list->next) { + font = (struct PdfFont *)list->data; + embed_pdffont(pdfbuf, &xref, font); + g_free(font->filename); + g_free(font->fontname); + g_free(font); + } + g_list_free(pdffonts); + // PDF trailer startxref = pdfbuf->len; if (annot) g_string_append_printf(pdfbuf, @@ -1027,7 +1402,7 @@ void print_background(GnomePrintContext *gpc, struct Page *pg, gboolean *abort) if (pg->bg->type == BG_SOLID) { gnome_print_setopacity(gpc, 1.0); gnome_print_setrgbcolor(gpc, RGBA_RGB(pg->bg->color_rgba)); - gnome_print_rect_filled(gpc, 0, 0, pg->width, pg->height); + gnome_print_rect_filled(gpc, 0, 0, pg->width, -pg->height); if (!ui.print_ruling) return; if (pg->bg->ruling == RULING_NONE) return; @@ -1036,17 +1411,17 @@ void print_background(GnomePrintContext *gpc, struct Page *pg, gboolean *abort) if (pg->bg->ruling == RULING_GRAPH) { for (x=RULING_GRAPHSPACING; x width-1; x+=RULING_GRAPHSPACING) - gnome_print_line_stroked(gpc, x, 0, x, pg->height); + gnome_print_line_stroked(gpc, x, 0, x, -pg->height); for (y=RULING_GRAPHSPACING; y height-1; y+=RULING_GRAPHSPACING) - gnome_print_line_stroked(gpc, 0, y, pg->width, y); + gnome_print_line_stroked(gpc, 0, -y, pg->width, -y); return; } for (y=RULING_TOPMARGIN; y height-1; y+=RULING_SPACING) - gnome_print_line_stroked(gpc, 0, y, pg->width, y); + gnome_print_line_stroked(gpc, 0, -y, pg->width, -y); if (pg->bg->ruling == RULING_LINED) { gnome_print_setrgbcolor(gpc, RGBA_RGB(RULING_MARGIN_COLOR)); - gnome_print_line_stroked(gpc, RULING_LEFTMARGIN, 0, RULING_LEFTMARGIN, pg->height); + gnome_print_line_stroked(gpc, RULING_LEFTMARGIN, 0, RULING_LEFTMARGIN, -pg->height); } return; } @@ -1067,7 +1442,7 @@ void print_background(GnomePrintContext *gpc, struct Page *pg, gboolean *abort) if (gdk_pixbuf_get_bits_per_sample(pix) != 8) return; if (gdk_pixbuf_get_colorspace(pix) != GDK_COLORSPACE_RGB) return; gnome_print_gsave(gpc); - gnome_print_scale(gpc, pg->width, -pg->height); + gnome_print_scale(gpc, pg->width, pg->height); gnome_print_translate(gpc, 0., -1.); if (gdk_pixbuf_get_n_channels(pix) == 3) gnome_print_rgbimage(gpc, gdk_pixbuf_get_pixels(pix), @@ -1092,6 +1467,8 @@ void print_page(GnomePrintContext *gpc, struct Page *pg, int pageno, struct Item *item; int i; double *pt; + PangoFontDescription *font_desc; + PangoLayout *layout; if (pg==NULL) return; @@ -1102,7 +1479,7 @@ void print_page(GnomePrintContext *gpc, struct Page *pg, int pageno, scale = MIN(pgwidth/pg->width, pgheight/pg->height)*0.95; gnome_print_translate(gpc, (pgwidth - scale*pg->width)/2, (pgheight + scale*pg->height)/2); - gnome_print_scale(gpc, scale, -scale); + gnome_print_scale(gpc, scale, scale); gnome_print_setlinejoin(gpc, 1); // round gnome_print_setlinecap(gpc, 1); // round @@ -1117,22 +1494,36 @@ void print_page(GnomePrintContext *gpc, struct Page *pg, int pageno, for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next) { if (*abort) break; item = (struct Item *)itemlist->data; - if (item->type == ITEM_STROKE) { + if (item->type == ITEM_STROKE || item->type == ITEM_TEXT) { if ((item->brush.color_rgba & ~0xff) != (old_rgba & ~0xff)) gnome_print_setrgbcolor(gpc, RGBA_RGB(item->brush.color_rgba)); if ((item->brush.color_rgba & 0xff) != (old_rgba & 0xff)) gnome_print_setopacity(gpc, RGBA_ALPHA(item->brush.color_rgba)); + old_rgba = item->brush.color_rgba; + } + if (item->type == ITEM_STROKE) { if (item->brush.thickness != old_thickness) gnome_print_setlinewidth(gpc, item->brush.thickness); - old_rgba = item->brush.color_rgba; old_thickness = item->brush.thickness; gnome_print_newpath(gpc); pt = item->path->coords; - gnome_print_moveto(gpc, pt[0], pt[1]); + gnome_print_moveto(gpc, pt[0], -pt[1]); for (i=1, pt+=2; i path->num_points; i++, pt+=2) - gnome_print_lineto(gpc, pt[0], pt[1]); + gnome_print_lineto(gpc, pt[0], -pt[1]); gnome_print_stroke(gpc); } + if (item->type == ITEM_TEXT) { + layout = gnome_print_pango_create_layout(gpc); + font_desc = pango_font_description_from_string(item->font_name); + pango_font_description_set_absolute_size(font_desc, + item->font_size*PANGO_SCALE); + pango_layout_set_font_description(layout, font_desc); + pango_font_description_free(font_desc); + pango_layout_set_text(layout, item->text, -1); + gnome_print_moveto(gpc, item->bbox.left, -item->bbox.top); + gnome_print_pango_layout(gpc, layout); + g_object_unref(layout); + } } } diff --git a/src/xo-print.h b/src/xo-print.h index 1ad42d4..bdfeee7 100644 --- a/src/xo-print.h +++ b/src/xo-print.h @@ -26,6 +26,25 @@ typedef struct PdfObj { char **names; } PdfObj; +typedef struct PdfFont { + int n_obj; + gboolean used_in_this_page; + unsigned char *filename; + int font_id; + gboolean is_truetype; + int glyph_page; + int glyphmap[256]; + int advance[256]; + char *glyphpsnames[256]; + int num_glyphs_used; + // fields from the FT_Face + gdouble ft2ps; + int nglyphs; + int ascender, descender, xmin, xmax, ymin, ymax; // in PDF font units + gchar *fontname; + int flags; +} PdfFont; + #define PDFTYPE_CST 0 // intval: true=1, false=0, null=-1 #define PDFTYPE_INT 1 // intval #define PDFTYPE_REAL 2 // realval diff --git a/src/xournal.h b/src/xournal.h index 6e75f2b..38bb95b 100644 --- a/src/xournal.h +++ b/src/xournal.h @@ -1,6 +1,11 @@ #include #include +#define ENABLE_XINPUT_BUGFIX +/* comment out this line if you are experiencing calibration problems with + XInput and want to try things differently. This will probably break + on-the-fly display rotation after application startup, though. */ + // PREF FILES INFO #define CONFIG_DIR ".xournal" @@ -109,8 +114,6 @@ extern guint predef_bgcolors_rgba[COLOR_MAX]; #define TOOLOPT_ERASER_WHITEOUT 1 #define TOOLOPT_ERASER_STROKES 2 -#define HILITER_ALPHA_MASK 0xffffff80 - extern double predef_thickness[NUM_STROKE_TOOLS][THICKNESS_MAX]; typedef struct BBox { @@ -122,10 +125,16 @@ struct UndoErasureData; typedef struct Item { int type; struct Brush brush; // the brush to use, if ITEM_STROKE + // 'brush" also contains color info for text items GnomeCanvasPoints *path; GnomeCanvasItem *canvas_item; // the corresponding canvas item, or NULL struct BBox bbox; struct UndoErasureData *erasure; // for temporary use during erasures + // the following fields for ITEM_TEXT: + gchar *text; + gchar *font_name; + gdouble font_size; + GtkWidget *widget; // the widget while text is being edited (ITEM_TEMP_TEXT) } Item; // item type values for Item.type, UndoItem.type, ui.cur_item_type ... @@ -148,6 +157,10 @@ typedef struct Item { #define ITEM_REPAINTSEL 15 #define ITEM_MOVESEL_VERT 16 #define ITEM_HAND 17 +#define ITEM_TEXT 18 +#define ITEM_TEMP_TEXT 19 +#define ITEM_TEXT_EDIT 20 +#define ITEM_TEXT_ATTRIB 21 typedef struct Layer { GList *items; // the items on the layer, from bottom to top @@ -209,6 +222,8 @@ typedef struct UIData { gboolean is_corestroke; // this stroke is painted with core pointer int screen_width, screen_height; // initial screen size, for XInput events double hand_refpt[2]; + int hand_scrollto_cx, hand_scrollto_cy; + gboolean hand_scrollto_pending; char *filename; gchar *default_path; // default path for new notes gboolean view_continuous, fullscreen, maximize_at_start; @@ -233,6 +248,11 @@ typedef struct UIData { GKeyFile *config_data; #endif int vertical_order[2][VBOX_MAIN_NITEMS]; // the order of interface components + gchar *default_font_name, *font_name; + gdouble default_font_size, font_size; + gulong resize_signal_handler; + gdouble hiliter_opacity; + guint hiliter_alpha_mask; } UIData; #define BRUSH_LINKED 0 @@ -248,8 +268,8 @@ typedef struct UndoErasureData { typedef struct UndoItem { int type; - struct Item *item; // for ITEM_STROKE - struct Layer *layer; // for ITEM_STROKE, ITEM_ERASURE, ITEM_PASTE, ITEM_NEW_LAYER, ITEM_DELETE_LAYER, ITEM_MOVESEL + struct Item *item; // for ITEM_STROKE, ITEM_TEXT, ITEM_TEXT_EDIT, ITEM_TEXT_ATTRIB + struct Layer *layer; // for ITEM_STROKE, ITEM_ERASURE, ITEM_PASTE, ITEM_NEW_LAYER, ITEM_DELETE_LAYER, ITEM_MOVESEL, ITEM_TEXT, ITEM_TEXT_EDIT struct Layer *layer2; // for ITEM_DELETE_LAYER with val=-1, ITEM_MOVESEL struct Page *page; // for ITEM_NEW_BG_ONE/RESIZE, ITEM_NEW_PAGE, ITEM_NEW_LAYER, ITEM_DELETE_LAYER, ITEM_DELETE_PAGE GList *erasurelist; // for ITEM_ERASURE @@ -257,7 +277,9 @@ typedef struct UndoItem { GList *auxlist; // for ITEM_REPAINTSEL (brushes), ITEM_MOVESEL (depths) struct Background *bg; // for ITEM_NEW_BG_ONE/RESIZE, ITEM_NEW_DEFAULT_BG int val; // for ITEM_NEW_PAGE, ITEM_NEW_LAYER, ITEM_DELETE_LAYER, ITEM_DELETE_PAGE - double val_x, val_y; // for ITEM_MOVESEL, ITEM_NEW_BG_RESIZE, ITEM_PAPER_RESIZE, ITEM_NEW_DEFAULT_BG + double val_x, val_y; // for ITEM_MOVESEL, ITEM_NEW_BG_RESIZE, ITEM_PAPER_RESIZE, ITEM_NEW_DEFAULT_BG, ITEM_TEXT_ATTRIB + gchar *str; // for ITEM_TEXT_EDIT, ITEM_TEXT_ATTRIB + struct Brush *brush; // for ITEM_TEXT_ATTRIB struct UndoItem *next; int multiop; } UndoItem; diff --git a/xournal.glade b/xournal.glade index 1752fff..471cd10 100644 --- a/xournal.glade +++ b/xournal.glade @@ -17,6 +17,7 @@ GDK_WINDOW_TYPE_HINT_NORMAL GDK_GRAVITY_NORTH_WEST True +False @@ -28,6 +29,8 @@ @@ -408,15 +419,17 @@@@ -335,7 +343,7 @@ True +GTK_PACK_DIRECTION_LTR +GTK_PACK_DIRECTION_LTR @@ -316,6 +323,7 @@ @@ -50,7 +53,7 @@ @@ -274,6 +280,7 @@ True -Annotate PDF +Annotate PD_F True @@ -104,7 +107,7 @@ True -Recent Files +Recent Doc_uments True @@ -219,15 +222,17 @@ gtk-print True + @@ -265,6 +270,7 @@ True -Export to PDF +_Export to PDF True + gtk-undo True + gtk-redo True + gtk-delete True + @@ -399,6 +409,7 @@ True -Continuous +_Continuous True True @@ -345,7 +353,7 @@ @@ -390,6 +399,7 @@ True -One Page +_One Page True True viewContinuous @@ -366,6 +374,7 @@True False + gtk-zoom-in True + gtk-zoom-out True + gtk-zoom-100 True + True -Page Width +Page _Width True + @@ -435,7 +448,7 @@ @@ -454,9 +467,10 @@ True -Set Zoom +_Set Zoom True True -First Page +_First Page True + @@ -475,9 +489,10 @@ True -Previous Page +_Previous Page True + @@ -496,9 +511,10 @@ True -Next Page +_Next Page True + @@ -517,9 +533,10 @@ True -Last Page +_Last Page True + @@ -544,7 +561,7 @@ True -Show Layer +_Show Layer True @@ -565,7 +582,7 @@ True -Hide Layer +_Hide Layer True @@ -599,7 +616,7 @@ @@ -608,7 +625,7 @@ True -New Page Before +New Page _Before True @@ -617,7 +634,7 @@ True -New Page After +New Page _After True @@ -626,7 +643,7 @@ True -New Page At End +New Page At _End True @@ -641,7 +658,7 @@ True -Delete Page +_Delete Page True @@ -650,7 +667,7 @@ True -New Layer +_New Layer True @@ -659,7 +676,7 @@ True -Delete Layer +Delete La_yer True @@ -674,7 +691,7 @@ True -Flatten +_Flatten True @@ -683,7 +700,7 @@ True -Paper Size +Paper Si_ze True True -Paper Color +Paper _Color True @@ -692,7 +709,7 @@ True -white paper +_white paper True True @@ -702,7 +719,7 @@ True -yellow paper +_yellow paper True True papercolorWhite @@ -713,7 +730,7 @@True -pink paper +_pink paper True True papercolorWhite @@ -724,7 +741,7 @@True -orange paper +_orange paper True True papercolorWhite @@ -735,7 +752,7 @@True -blue paper +_blue paper True True papercolorWhite @@ -746,7 +763,7 @@True -green paper +_green paper True True papercolorWhite @@ -781,7 +798,7 @@True -Paper Style +Paper _Style True @@ -790,7 +807,7 @@ True -plain +_plain True True @@ -800,7 +817,7 @@ True -lined +_lined True True paperstylePlain @@ -811,7 +828,7 @@@@ -978,44 +999,48 @@ True -ruled +_ruled True True paperstylePlain @@ -822,7 +839,7 @@@@ -966,6 +986,7 @@ True -graph +_graph True True paperstylePlain @@ -846,7 +863,7 @@@@ -955,6 +974,7 @@ True -Apply To All Pages +Apply _To All Pages True False @@ -862,7 +879,7 @@ @@ -944,6 +962,7 @@ True -Load Background +_Load Background True @@ -883,7 +900,7 @@ @@ -898,7 +915,7 @@ True -Background Screenshot +Background Screens_hot True @@ -907,7 +924,7 @@ True -Default Paper +Default _Paper True @@ -933,6 +950,7 @@ True -Set As Default +Set As De_fault True True True + True toolsPen + True toolsPen + True toolsPen + True -_Select Region +Select Re_gion True True toolsPen + True -Select Rectangle +Select _Rectangle True True toolsPen + True -Vertical Space +_Vertical Space True True toolsPen + @@ -1049,7 +1074,7 @@ True -Hand Tool +H_and Tool True False toolsPen + True -black +blac_k True True @@ -1059,7 +1084,7 @@ True -blue +_blue True True colorBlack @@ -1070,7 +1095,7 @@True -red +_red True True colorBlack @@ -1081,7 +1106,7 @@True -green +_green True True colorBlack @@ -1092,7 +1117,7 @@True -gray +gr_ay True True colorBlack @@ -1109,7 +1134,7 @@True -light blue +light bl_ue True True colorBlack @@ -1120,7 +1145,7 @@True -light green +light gr_een True True colorBlack @@ -1131,7 +1156,7 @@True -magenta +_magenta True True colorBlack @@ -1142,7 +1167,7 @@True -orange +_orange True True colorBlack @@ -1153,7 +1178,7 @@True -yellow +_yellow True True colorBlack @@ -1164,7 +1189,7 @@True -white +_white True True colorBlack @@ -1208,7 +1233,7 @@True -very fine +_very fine True True @@ -1218,7 +1243,7 @@ True -fine +_fine True True penthicknessVeryFine @@ -1229,7 +1254,7 @@True -medium +_medium True True penthicknessVeryFine @@ -1240,7 +1265,7 @@True -thick +_thick True True penthicknessVeryFine @@ -1251,7 +1276,7 @@True -very thick +ver_y thick True True penthicknessVeryFine @@ -1266,7 +1291,7 @@True -Eraser Options +Eraser Optio_ns True @@ -1275,7 +1300,7 @@ True -fine +_fine True True @@ -1285,7 +1310,7 @@ True -medium +_medium True True eraserFine @@ -1296,7 +1321,7 @@True -thick +_thick True True eraserFine @@ -1313,7 +1338,7 @@True -standard +_standard True True @@ -1323,7 +1348,7 @@ True -whiteout +_whiteout True True eraserStandard @@ -1334,7 +1359,7 @@True -delete strokes +_delete strokes True True eraserStandard @@ -1349,7 +1374,7 @@True -Highlighter Options +Highlighter Opt_ions True @@ -1358,7 +1383,7 @@ True -fine +_fine True True @@ -1368,7 +1393,7 @@ True -medium +_medium True True highlighterFine @@ -1379,7 +1404,7 @@True -thick +_thick True True highlighterFine @@ -1394,9 +1419,10 @@True -Text Font +Text _Font... True + @@ -1421,7 +1447,7 @@ @@ -1495,7 +1522,7 @@@@ -1448,7 +1474,7 @@ True -Default Pen +_Default Pen True @@ -1457,7 +1483,7 @@ True -Default Text +Default Te_xt True @@ -1472,10 +1498,11 @@ True -Set As Default +_Set As Default True True -Ruler +Ru_ler True False + True -Use XInput +Use _XInput True False @@ -1505,7 +1532,7 @@ True -Discard Core Events +Discard _Core Events True False @@ -1515,7 +1542,7 @@ True -Eraser Tip +_Eraser Tip True False @@ -1525,7 +1552,7 @@ True -Button 2 Mapping +Button _2 Mapping True @@ -1534,7 +1561,7 @@ True -Pen +_Pen True True @@ -1544,7 +1571,7 @@ True -Eraser +_Eraser True True button2Pen @@ -1555,7 +1582,7 @@True -Highlighter +_Highlighter True True button2Pen @@ -1566,7 +1593,7 @@True -Text +_Text True True button2Pen @@ -1577,7 +1604,7 @@True -Select Region +Select Re_gion True True button2Pen @@ -1588,7 +1615,7 @@True -Select Rectangle +Select _Rectangle True True button2Pen @@ -1599,7 +1626,7 @@True -Vertical Space +_Vertical Space True True button2Pen @@ -1610,7 +1637,7 @@True -Hand Tool +H_and Tool True False button2Pen @@ -1627,7 +1654,7 @@True -Link to Primary Brush +_Link to Primary Brush True True @@ -1637,7 +1664,7 @@ True -Copy of Current Brush +_Copy of Current Brush True True button2LinkBrush @@ -1661,7 +1688,7 @@True -Button 3 Mapping +Button _3 Mapping True @@ -1670,7 +1697,7 @@ True -Pen +_Pen True True @@ -1680,7 +1707,7 @@ True -Eraser +_Eraser True True button3Pen @@ -1691,7 +1718,7 @@True -Highlighter +_Highlighter True True button3Pen @@ -1702,7 +1729,7 @@True -Text +_Text True True button3Pen @@ -1713,7 +1740,7 @@True -Select Region +Select Re_gion True True button3Pen @@ -1724,7 +1751,7 @@True -Select Rectangle +Select _Rectangle True True button3Pen @@ -1735,7 +1762,7 @@True -Vertical Space +_Vertical Space True True button3Pen @@ -1746,7 +1773,7 @@True -Hand Tool +H_and Tool True False button3Pen @@ -1763,7 +1790,7 @@True -Link to Primary Brush +_Link to Primary Brush True True @@ -1773,7 +1800,7 @@ True -Copy of Current Brush +_Copy of Current Brush True True button3LinkBrush @@ -1803,7 +1830,7 @@True -Antialiased Bitmaps +_Antialiased Bitmaps True False @@ -1813,7 +1840,7 @@ - True -Progressive Backgrounds +_Progressive Backgrounds True False @@ -1823,7 +1850,7 @@ True -Print Paper Ruling +Print Paper _Ruling True False @@ -1839,7 +1866,7 @@ + + @@ -2878,6 +2905,51 @@ True -Save Preferences +_Save Preferences True True + + ++ +True +True +True +False + ++ ++ +True ++ +False +False ++ + +True +True +True +False + ++ ++ +True +True +True +True +True +False +False ++ + +False +False +0 @@ -3056,120 +3128,6 @@- - -4 -True -Select Font -GTK_WINDOW_TOPLEVEL -GTK_WIN_POS_NONE -False -True -False -True -False -False -GDK_WINDOW_TYPE_HINT_DIALOG -GDK_GRAVITY_NORTH_WEST -True - -- - -- -True -True -True -GTK_RELIEF_NORMAL -True -- - -- -True -True -True -GTK_RELIEF_NORMAL -True -- - -- -True -True -True -GTK_RELIEF_NORMAL -True -- -- -4 -True -abcdefghijk ABCDEFGHIJK -- -0 -True -True -- -True -Select Color -GTK_WINDOW_TOPLEVEL -GTK_WIN_POS_NONE -False -False -False -True -False -False -GDK_WINDOW_TYPE_HINT_DIALOG -GDK_GRAVITY_NORTH_WEST -True - -- - -- -True -True -True -GTK_RELIEF_NORMAL -True -- - -- -True -True -True -GTK_RELIEF_NORMAL -True -- - -- -True -True -True -GTK_RELIEF_NORMAL -True -- -- -True -False -False -True Set Paper Size @@ -3184,6 +3142,7 @@GDK_WINDOW_TYPE_HINT_DIALOG GDK_GRAVITY_NORTH_WEST True +False True @@ -3428,6 +3387,7 @@ points GDK_WINDOW_TYPE_HINT_DIALOG GDK_GRAVITY_NORTH_WEST True +False True @@ -3546,6 +3506,7 @@ points GDK_WINDOW_TYPE_HINT_DIALOG GDK_GRAVITY_NORTH_WEST True +False True