├── po ├── POTFILES.skip ├── meson.build ├── POTFILES.in ├── LINGUAS └── Makevars ├── mate-calc.png ├── ChangeLog ├── src ├── utility.h ├── mp-enums.h.template ├── mp-enums.c.template ├── financial.h ├── math-variable-popup.h ├── math-preferences.h ├── math-display.h ├── mate-calc.about ├── lexer.h ├── math-variables.h ├── currency-manager.h ├── org.mate.calculator.gresource.xml ├── math-buttons.h ├── currency.h ├── math-history-entry.h ├── math-converter.h ├── unit.h ├── parserfunc.h ├── math-history.h ├── unit-manager.h ├── unit-category.h ├── math-window.h ├── mp-equation.h ├── parser.h ├── currency.c ├── mp-equation-private.h ├── mate-calc-cmd.c ├── mp-serializer.h ├── meson.build ├── prelexer.h ├── history-entry.ui ├── unit-category.c ├── math-history-entry.c ├── Makefile.am ├── math-variables.c ├── mp-equation-lexer.l ├── math-equation.h ├── unit.c ├── math-history.c ├── mp-binary.c ├── prelexer.c ├── mp-trigonometric.c └── test-mp.c ├── makepot ├── .github ├── issue_template.md ├── FUNDING.yml └── workflows │ ├── notify.yml │ ├── release.yml │ ├── pages.yml │ ├── quality.yml │ └── build.yml ├── .tx ├── config_20221024111755.bak └── config ├── help ├── C │ ├── modulus.page │ ├── factorial.page │ ├── conv-base.page │ ├── absolute.page │ ├── legal.xml │ ├── conv-time.page │ ├── conv-weight.page │ ├── conv-character.page │ ├── factorize.page │ ├── conv-length.page │ ├── conv-currency.page │ ├── boolean.page │ ├── percentage.page │ ├── index.page │ ├── logarithm.page │ ├── mouse.page │ ├── scientific.page │ ├── base.page │ ├── equation.page │ ├── trigonometry.page │ ├── power.page │ ├── complex.page │ ├── number-display.page │ ├── variables.page │ ├── superscript.page │ ├── keyboard.page │ ├── functions.page │ └── financial.page ├── meson.build ├── LINGUAS └── Makefile.am ├── meson-postinstall.sh ├── autogen.sh ├── data ├── meson.build ├── mate-calc-cmd.1 ├── mate-calc.desktop.in ├── Makefile.am ├── mate-calc.appdata.xml.in ├── mate-calc.1 └── org.mate.calc.gschema.xml ├── Makefile.am ├── meson.build ├── README.md ├── AUTHORS ├── configure.ac └── update-authors.pl /po/POTFILES.skip: -------------------------------------------------------------------------------- 1 | src/mp-equation-parser.c 2 | -------------------------------------------------------------------------------- /po/meson.build: -------------------------------------------------------------------------------- 1 | i18n.gettext(meson.project_name(), 2 | preset: 'glib' 3 | ) 4 | -------------------------------------------------------------------------------- /mate-calc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mate-desktop/mate-calc/HEAD/mate-calc.png -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | The ChangeLog is auto-generated when releasing. If you are seeing this, use 2 | 'git log' for a detailed list of changes. 3 | -------------------------------------------------------------------------------- /src/utility.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILITY_H 2 | #define UTILITY_H 3 | 4 | #include 5 | #include "config.h" 6 | 7 | extern GSettings *g_settings_var; 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /makepot: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | PACKAGE=mate-calc; 4 | 5 | # normal translations 6 | make -C po $PACKAGE.pot && mv po/$PACKAGE.pot . 7 | sed -i "/#, fuzzy/d" $PACKAGE.pot 8 | 9 | # translations for user-quide 10 | rm -f help/$PACKAGE.pot && 11 | make -C help $PACKAGE.pot 12 | -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | #### Expected behaviour 2 | 3 | 4 | #### Actual behaviour 5 | 6 | 7 | #### Steps to reproduce the behaviour 8 | 9 | 10 | #### MATE general version 11 | 12 | 13 | #### Package version 14 | 15 | 16 | #### Linux Distribution 17 | 18 | 19 | #### Link to bugreport of your Distribution (requirement) 20 | -------------------------------------------------------------------------------- /.tx/config_20221024111755.bak: -------------------------------------------------------------------------------- 1 | [main] 2 | host = https://www.transifex.com 3 | 4 | [MATE.master--mate-calc] 5 | file_filter = po/.po 6 | source_file = mate-calc.pot 7 | source_lang = en 8 | type = PO 9 | minimum_perc = 2 10 | 11 | [MATE.master--mate-calc-user-guide] 12 | file_filter = help//.po 13 | source_file = help/mate-calc.pot 14 | source_lang = en 15 | type = PO 16 | minimum_perc = 2 17 | 18 | -------------------------------------------------------------------------------- /.tx/config: -------------------------------------------------------------------------------- 1 | [main] 2 | host = https://www.transifex.com 3 | 4 | [o:mate:p:MATE:r:master--mate-calc] 5 | file_filter = po/.po 6 | source_file = mate-calc.pot 7 | source_lang = en 8 | type = PO 9 | minimum_perc = 2 10 | 11 | [o:mate:p:MATE:r:master--mate-calc-user-guide] 12 | file_filter = help//.po 13 | source_file = help/mate-calc.pot 14 | source_lang = en 15 | type = PO 16 | minimum_perc = 2 17 | 18 | -------------------------------------------------------------------------------- /help/C/modulus.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | Modulus Division 10 | 11 |

12 | Modulus division is performed using the mod operator. 13 |

14 | 15 |

16 | 9 mod 5 17 |

18 |
19 |
20 | -------------------------------------------------------------------------------- /meson-postinstall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Package managers set this so we don't need to run 4 | 5 | if [ -z "$DESTDIR" ]; then 6 | echo Compiling GSettings schemas... 7 | glib-compile-schemas ${MESON_INSTALL_PREFIX}/share/glib-2.0/schemas 8 | 9 | echo Updating desktop database... 10 | update-desktop-database -q ${MESON_INSTALL_PREFIX}/share/applications 11 | 12 | ln -sf ${MESON_INSTALL_PREFIX}/bin/'mate-calc' ${MESON_INSTALL_PREFIX}/bin/'mate-calculator' 13 | fi 14 | -------------------------------------------------------------------------------- /help/C/factorial.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | Factorials 10 | 11 |

12 | Factorials are entered using the ! symbol. 13 | To calculate the factorial of 6 enter the following. 14 |

15 | 16 |

17 | 6! 18 |

19 |
20 |
21 | -------------------------------------------------------------------------------- /help/C/conv-base.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | Number Bases 10 | 11 |

12 | To convert between number bases enter a number (or solve an equation) and change the result format from the CalculatorPreferences menu. 13 |

14 |
15 | -------------------------------------------------------------------------------- /help/C/absolute.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | Absolute Values 10 | 11 |

12 | Absolute values are calculated using the | symbol or abs function. 13 |

14 | 15 |

16 | |−1| 17 |

18 |

19 | abs (−1) 20 |

21 |
22 |
23 | -------------------------------------------------------------------------------- /help/C/legal.xml: -------------------------------------------------------------------------------- 1 | 3 |

This work is licensed under a 4 | Creative Commons 5 | Attribution-Share Alike 3.0 Unported License.

6 |

As a special exception, the copyright holders give you permission to copy, 7 | modify, and distribute the example code contained in this document under the 8 | terms of your choosing, without restriction.

9 |
10 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | custom: https://mate-desktop.org/donate/ 10 | -------------------------------------------------------------------------------- /help/C/conv-time.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | Time 10 | 11 |

12 | To convert between time use the in operator. 13 |

14 | 15 |

16 | 3 years in hours 17 |

18 |
19 | 20 |

21 | Time conversions must be performed using the keyboard. 22 |

23 |
24 |
25 | -------------------------------------------------------------------------------- /help/C/conv-weight.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | Mass 10 | 11 |

12 | To convert between mass use the in operator. 13 |

14 | 15 |

16 | 1kg in pounds 17 |

18 |
19 | 20 |

21 | Mass conversions must be performed using the keyboard. 22 |

23 |
24 |
25 | -------------------------------------------------------------------------------- /help/C/conv-character.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | Character Codes 10 | 11 |

12 | When in programming mode the á button opens a dialog to convert characters to character codes. 13 |

14 | 15 |

16 | Characters cannot be converted using the keyboard. 17 |

18 |
19 |
20 | -------------------------------------------------------------------------------- /src/mp-enums.h.template: -------------------------------------------------------------------------------- 1 | /*** BEGIN file-header ***/ 2 | 3 | #ifndef __MATH_ENUMS_H__ 4 | #define __MATH_ENUMS_H__ 5 | 6 | #include 7 | 8 | G_BEGIN_DECLS 9 | /*** END file-header ***/ 10 | 11 | /*** BEGIN file-production ***/ 12 | 13 | /* enumerations from "@filename@" */ 14 | /*** END file-production ***/ 15 | 16 | /*** BEGIN value-header ***/ 17 | GType math_@enum_name@_get_type (void) G_GNUC_CONST; 18 | #define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (math_@enum_name@_get_type ()) 19 | /*** END value-header ***/ 20 | 21 | /*** BEGIN file-tail ***/ 22 | G_END_DECLS 23 | 24 | #endif /* __MATH_ENUMS_H__ */ 25 | /*** END file-tail ***/ 26 | -------------------------------------------------------------------------------- /help/C/factorize.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | Factorization 10 | 11 |

12 | You can factorize the number currently displayed by pressing CtrlF or by pressing the fact button. 13 | This button is visible in programming mode. 14 |

15 |

16 | To factorize integers bigger than 2^64 the Miller-Rabin primality test and Pollard's rho algorithm are used. 17 |

18 |
19 | -------------------------------------------------------------------------------- /help/C/conv-length.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | Length/Area/Volume 10 | 11 |

12 | To convert between length, area and volume units use the in operator. 13 |

14 | 15 |

16 | 6 meters in inches 17 |

18 |

19 | 1 acre in cm² 20 |

21 |

22 | 1 pint in mL 23 |

24 |
25 | 26 |

27 | Length/Area/Volume conversions must be performed using the keyboard. 28 |

29 |
30 |
31 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Run this to generate all the initial makefiles, etc. 3 | 4 | srcdir=`dirname $0` 5 | test -z "$srcdir" && srcdir=. 6 | 7 | PKG_NAME="mate-calc" 8 | REQUIRED_AUTOMAKE_VERSION=1.7 9 | REQUIRED_YELP_TOOLS_VERSION=3.1.1 10 | 11 | (test -f $srcdir/configure.ac \ 12 | && test -d $srcdir/src) || { 13 | echo -n "**Error**: Directory "\`$srcdir\'" does not look like the" 14 | echo " top-level mate-calc directory" 15 | exit 1 16 | } 17 | 18 | which mate-autogen || { 19 | echo "You need to install mate-common from the MATE git" 20 | exit 1 21 | } 22 | 23 | which yelp-build || { 24 | echo "You need to install yelp-tools" 25 | exit 1 26 | } 27 | 28 | USE_COMMON_DOC_BUILD=yes . mate-autogen 29 | -------------------------------------------------------------------------------- /data/meson.build: -------------------------------------------------------------------------------- 1 | # Desktop file 2 | i18n.merge_file( 3 | input: 'mate-calc.desktop.in', 4 | output: 'mate-calc.desktop', 5 | type: 'desktop', 6 | po_dir: po_dir, 7 | install: true, 8 | install_dir: join_paths(get_option('datadir'), 'applications'), 9 | ) 10 | 11 | # Appdata 12 | i18n.merge_file( 13 | input: 'mate-calc.appdata.xml.in', 14 | output: 'mate-calc.appdata.xml', 15 | type: 'xml', 16 | po_dir: po_dir, 17 | install: true, 18 | install_dir: join_paths(get_option('datadir'), 'metainfo') 19 | ) 20 | 21 | # Gschema 22 | install_data('org.mate.calc.gschema.xml', 23 | install_dir: join_paths(get_option('datadir'), 'glib-2.0', 'schemas'), 24 | ) 25 | 26 | # Manpage 27 | install_man( 28 | 'mate-calc-cmd.1', 29 | 'mate-calc.1' 30 | ) 31 | -------------------------------------------------------------------------------- /help/C/conv-currency.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | Currency 10 | 11 |

12 | To convert currencies, enter the financial mode, and use the currency controls. 13 |

14 |

15 | You can also convert currencies using the keyboard and the in operator. 16 |

17 | 18 |

19 | 13.65 USD in GBP 20 |

21 |
22 | 23 |

24 | Currency information is approximate and should not be used for making financial decisions. 25 |

26 |
27 |
28 | -------------------------------------------------------------------------------- /data/mate-calc-cmd.1: -------------------------------------------------------------------------------- 1 | .\" Copyright (c) 2011 Jean Schurger 2 | .\" Man page for mate-calc 3 | .TH MATE-CALC-CMD 1 "1 February 2014" "MATE Desktop Environment" "General Manual" 4 | .\" Please adjust this date when revising the manpage. 5 | .\" 6 | .SH "NAME" 7 | mate-calc-cmd \- A console calculator for the MATE Desktop Environment. 8 | .SH "SYNOPSIS" 9 | \fBmate-calc-cmd\fR 10 | .SH "DESCRIPTION" 11 | \fBmate-calc-cmd\fR is the console version of \fBmate-calc\fR, the calculator for the MATE Desktop Environment. 12 | .SH "BUGS" 13 | .SS Should you encounter any bugs, they may be reported at: 14 | http://github.com/mate-desktop/mate-calc/issues 15 | .SH "SEE ALSO" 16 | .SS Further information may also be available at: http://wiki.mate-desktop.org/docs 17 | .P 18 | .BR mate-calc (1) 19 | -------------------------------------------------------------------------------- /data/mate-calc.desktop.in: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=MATE Calculator 3 | GenericName=Calculator 4 | Comment=Perform arithmetic, scientific or financial calculations 5 | Exec=mate-calc 6 | # Translators: Do NOT translate or transliterate this text (this is an icon file name)! 7 | Icon=accessories-calculator 8 | Terminal=false 9 | Type=Application 10 | StartupNotify=true 11 | # Translators: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! 12 | Keywords=calculator;MATE;scientific;arithmetic;financial;calculations; 13 | Categories=GTK;Utility;Calculator; 14 | X-MATE-DocPath=mate-calc/mate-calc.xml 15 | X-MATE-Bugzilla-Bugzilla=MATE 16 | X-MATE-Bugzilla-Product=mate-calc 17 | X-MATE-Bugzilla-Component=general 18 | X-MATE-Bugzilla-OtherBinaries=mate-calculator 19 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = po src data help 2 | 3 | # Temporary fix for JHBuild, see https://bugzilla.gnome.org/show_bug.cgi?id=641652 4 | ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS} 5 | 6 | DISTCLEANFILES = \ 7 | Makefile.in \ 8 | aclocal.m4 \ 9 | config.h.in \ 10 | configure \ 11 | depcomp \ 12 | install-sh \ 13 | missing \ 14 | mkinstalldirs \ 15 | omf.make \ 16 | xmldocs.make 17 | 18 | DISTCHECK_CONFIGURE_FLAGS = \ 19 | --enable-compile-warnings=no \ 20 | CFLAGS='-Wno-deprecated-declarations' 21 | 22 | EXTRA_DIST = \ 23 | autogen.sh \ 24 | README.md 25 | 26 | 27 | # Build ChangeLog from GIT history 28 | ChangeLog: 29 | $(AM_V_GEN) if test -d $(top_srcdir)/.git; then \ 30 | GIT_DIR="$(top_srcdir)/.git" git log --stat > $@; \ 31 | fi 32 | 33 | dist: ChangeLog 34 | 35 | .PHONY: ChangeLog 36 | 37 | -include $(top_srcdir)/git.mk 38 | -------------------------------------------------------------------------------- /help/meson.build: -------------------------------------------------------------------------------- 1 | mate_calc_help_pages = [ 2 | 'absolute.page', 3 | 'base.page', 4 | 'boolean.page', 5 | 'complex.page', 6 | 'conv-base.page', 7 | 'conv-character.page', 8 | 'conv-currency.page', 9 | 'conv-length.page', 10 | 'conv-time.page', 11 | 'conv-weight.page', 12 | 'equation.page', 13 | 'factorial.page', 14 | 'factorize.page', 15 | 'financial.page', 16 | 'functions.page', 17 | 'index.page', 18 | 'keyboard.page', 19 | 'legal.xml', 20 | 'logarithm.page', 21 | 'modulus.page', 22 | 'mouse.page', 23 | 'number-display.page', 24 | 'percentage.page', 25 | 'power.page', 26 | 'scientific.page', 27 | 'superscript.page', 28 | 'trigonometry.page', 29 | 'variables.page' 30 | ] 31 | gnome.yelp(meson.project_name(), 32 | sources: mate_calc_help_pages, 33 | ) 34 | -------------------------------------------------------------------------------- /po/POTFILES.in: -------------------------------------------------------------------------------- 1 | # List of source files containing translatable strings. 2 | # Please keep this file sorted alphabetically. 3 | src/buttons-advanced.ui 4 | src/buttons-basic.ui 5 | src/buttons-financial.ui 6 | src/buttons-programming.ui 7 | src/preferences.ui 8 | data/mate-calc.appdata.xml.in 9 | data/mate-calc.desktop.in 10 | data/org.mate.calc.gschema.xml 11 | src/currency.c 12 | src/currency-manager.c 13 | src/financial.c 14 | src/mate-calc-cmd.c 15 | src/mate-calc.c 16 | src/math-buttons.c 17 | src/math-converter.c 18 | src/math-display.c 19 | src/math-equation.c 20 | src/math-preferences.c 21 | src/math-variable-popup.c 22 | src/math-variables.c 23 | src/math-window.c 24 | src/mp-binary.c 25 | src/mp.c 26 | src/mp-convert.c 27 | src/mp-equation.c 28 | src/mp-serializer.c 29 | src/mp-trigonometric.c 30 | src/unit.c 31 | src/unit-category.c 32 | src/unit-manager.c 33 | -------------------------------------------------------------------------------- /help/C/boolean.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | Boolean Algebra 10 | 11 |

12 | Boolean algebra can be calculated using the AND, OR and XOR operators. 13 |

14 | 15 |

16 | 010011₂ AND 110101₂ 17 |

18 |
19 |

20 | Buttons for these symbols are available in programming mode. 21 |

22 |

23 | The NOT function inverts the bits in a number. 24 | The word size is set from the CalculatorPreferences menu. 25 |

26 | 27 |

28 | NOT 010011₂ 29 |

30 |
31 |
32 | -------------------------------------------------------------------------------- /help/C/percentage.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | Percentages 10 | 11 |

12 | Percentages are calculated using the % symbol. 13 |

14 |

15 | When added or subtracted the percentage symbol resolves to one percent of the value being added or subtracted from. 16 | The following equation calculates the price of a $140 item with 15% tax (140 + (15÷100)×140). 17 |

18 | 19 |

20 | 140+15% 21 |

22 |
23 |

24 | In all other cases the percentage symbol resolves to a fraction out of 100. 25 | The following equation calculates one quarter of 80 apples ((25÷100)×80). 26 |

27 | 28 |

29 | 25%×80 30 |

31 |
32 |
33 | -------------------------------------------------------------------------------- /help/C/index.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | Robert Ancell 8 | robert.ancell@gmail.com 9 | 10 | 11 | 12 | 13 | MATE Calculator Help 14 | 15 |
16 | User Interface 17 |
18 | 19 |
20 | Equations 21 |
22 | 23 |
24 | Numbers 25 |
26 | 27 |
28 | Conversions 29 |
30 | 31 |
32 | Financial Calculations 33 |
34 |
35 | -------------------------------------------------------------------------------- /src/mp-enums.c.template: -------------------------------------------------------------------------------- 1 | /*** BEGIN file-header ***/ 2 | #include "mp-serializer.h" 3 | #include "mp-enums.h" 4 | 5 | /*** END file-header ***/ 6 | 7 | /*** BEGIN file-production ***/ 8 | /* enumerations from "@filename@" */ 9 | /*** END file-production ***/ 10 | 11 | /*** BEGIN value-header ***/ 12 | GType 13 | math_@enum_name@_get_type (void) 14 | { 15 | static GType etype = 0; 16 | if (G_UNLIKELY(etype == 0)) { 17 | static const G@Type@Value values[] = { 18 | /*** END value-header ***/ 19 | 20 | /*** BEGIN value-production ***/ 21 | { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, 22 | /*** END value-production ***/ 23 | 24 | /*** BEGIN value-tail ***/ 25 | { 0, NULL, NULL } 26 | }; 27 | etype = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); 28 | } 29 | return etype; 30 | } 31 | 32 | /*** END value-tail ***/ 33 | 34 | /*** BEGIN file-tail ***/ 35 | 36 | /*** END file-tail ***/ 37 | -------------------------------------------------------------------------------- /data/Makefile.am: -------------------------------------------------------------------------------- 1 | appdatadir = $(datadir)/metainfo 2 | appdata_in_files = mate-calc.appdata.xml.in 3 | appdata_DATA = $(appdata_in_files:.xml.in=.xml) 4 | $(appdata_DATA): $(appdata_in_files) 5 | $(AM_V_GEN) $(MSGFMT) --xml --template $< -d $(top_srcdir)/po -o $@ 6 | 7 | gsettings_SCHEMAS = org.mate.calc.gschema.xml 8 | @GSETTINGS_RULES@ 9 | 10 | Utilitiesdir = $(datadir)/applications 11 | Utilities_in_files = mate-calc.desktop.in 12 | Utilities_DATA = $(Utilities_in_files:.desktop.in=.desktop) 13 | $(Utilities_DATA): $(Utilities_in_files) 14 | $(AM_V_GEN) $(MSGFMT) --desktop --keyword= --keyword=Name --keyword=GenericName --keyword=Comment --keyword=Keywords --template $< -d $(top_srcdir)/po -o $@ 15 | 16 | man1_MANS = mate-calc.1 mate-calc-cmd.1 17 | 18 | EXTRA_DIST = \ 19 | mate-calc.desktop.in \ 20 | $(appdata_in_files) \ 21 | $(gsettings_SCHEMAS) \ 22 | $(man1_MANS) 23 | 24 | DISTCLEANFILES = \ 25 | Makefile.in \ 26 | mate-calc.desktop \ 27 | $(appdata_DATA) 28 | 29 | -include $(top_srcdir)/git.mk 30 | -------------------------------------------------------------------------------- /help/LINGUAS: -------------------------------------------------------------------------------- 1 | af 2 | am 3 | ar 4 | as 5 | ast 6 | az 7 | be 8 | bg 9 | bn 10 | bn_IN 11 | br 12 | bs 13 | ca 14 | ca@valencia 15 | cmn 16 | crh 17 | cs 18 | cy 19 | da 20 | de 21 | dz 22 | el 23 | en_AU 24 | en_CA 25 | en_GB 26 | eo 27 | es 28 | es_AR 29 | es_CO 30 | es_MX 31 | et 32 | eu 33 | fa 34 | fi 35 | fr 36 | frp 37 | fur 38 | ga 39 | gl 40 | gu 41 | ha 42 | he 43 | hi 44 | hr 45 | hu 46 | hy 47 | id 48 | ie 49 | ig 50 | is 51 | it 52 | ja 53 | ka 54 | kk 55 | km 56 | kn 57 | ko 58 | ku 59 | ku_IQ 60 | ky 61 | li 62 | lt 63 | lv 64 | mai 65 | mg 66 | mk 67 | ml 68 | mn 69 | mr 70 | ms 71 | my 72 | nb 73 | nds 74 | ne 75 | nl 76 | nn 77 | nso 78 | oc 79 | or 80 | pa 81 | pl 82 | pms 83 | ps 84 | pt 85 | pt_BR 86 | ro 87 | ru 88 | rw 89 | si 90 | sk 91 | sl 92 | sq 93 | sr 94 | sr@latin 95 | sv 96 | ta 97 | te 98 | th 99 | tk 100 | tr 101 | ug 102 | uk 103 | ur 104 | uz 105 | vi 106 | wa 107 | xh 108 | yo 109 | zh_CN 110 | zh_HK 111 | zh_TW 112 | zu 113 | -------------------------------------------------------------------------------- /help/C/logarithm.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | Logarithms 10 | 11 |

12 | Logarithms can be calculated using the log function. 13 |

14 | 15 |

16 | log 100 17 |

18 |
19 |

20 | To calculate a logarithm in a different base use a subscript number after the function. 21 |

22 | 23 |

24 | log₂ 32 25 |

26 |
27 |

28 | To calculate a natural logarithm use the ln function. 29 |

30 | 31 |

32 | ln 1.32 33 |

34 |
35 |

36 | Euler's number can be entered by using the variable e. 37 |

38 | 39 |

40 | e^1.32 41 |

42 |
43 |
44 | -------------------------------------------------------------------------------- /src/financial.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1987-2008 Sun Microsystems, Inc. All Rights Reserved. 3 | * Copyright (C) 2008-2011 Robert Ancell 4 | * 5 | * This program is free software: you can redistribute it and/or modify it under 6 | * the terms of the GNU General Public License as published by the Free Software 7 | * Foundation, either version 2 of the License, or (at your option) any later 8 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 9 | * license. 10 | */ 11 | 12 | #ifndef FINANCIAL_H 13 | #define FINANCIAL_H 14 | 15 | #include "mp.h" 16 | #include "math-equation.h" 17 | 18 | void do_finc_expression(MathEquation *equation, int function, MPNumber *arg1, MPNumber *arg2, MPNumber *arg3, MPNumber *arg4); 19 | 20 | enum finc_dialogs { 21 | FINC_CTRM_DIALOG, 22 | FINC_DDB_DIALOG, 23 | FINC_FV_DIALOG, 24 | FINC_GPM_DIALOG, 25 | FINC_PMT_DIALOG, 26 | FINC_PV_DIALOG, 27 | FINC_RATE_DIALOG, 28 | FINC_SLN_DIALOG, 29 | FINC_SYD_DIALOG, 30 | FINC_TERM_DIALOG 31 | }; 32 | 33 | #endif /* FINANCIAL_H */ 34 | -------------------------------------------------------------------------------- /help/C/mouse.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | Using the Mouse 10 | 11 |

12 | All equations can be entered using the mouse. 13 | To access all buttons there are a number of modes that can be selected from the Mode menu. 14 |

15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |

Basic

Provides buttons suitable for basic equations

Advanced

Provides buttons suitable for advanced mathematics such as

Financial

Provides buttons suitable for financial equations

Programming

Provides buttons suitable for computer programmers

33 |
34 | -------------------------------------------------------------------------------- /help/C/scientific.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | Scientific Notation 10 | 11 |

12 | To enter numbers in scientific format use the ×10x button (CtrlE). 13 | The number mode automatically changes to superscript. 14 | To enter 2×10¹⁰⁰, start by entering the mantissa (2): 15 |

16 | 17 |

18 | 2 19 |

20 |
21 |

22 | Then press the scientific notation button (or press CtrlE): 23 |

24 | 25 |

26 | 2×10 27 |

28 |
29 |

30 | Then enter the exponent (100): 31 |

32 | 33 |

34 | 2×10¹⁰⁰ 35 |

36 |
37 |

38 | To show results in scientific form change the result format. 39 |

40 |
41 | -------------------------------------------------------------------------------- /help/C/base.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | Number Bases 10 | 11 |

12 | To enter numbers in a particular number base use subscript numbers. 13 | The following numbers are equivalent. 14 |

15 | 16 |

17 | 1001011₂ 18 |

19 |

20 | 113₈ 21 |

22 |

23 | 75 24 |

25 |

26 | 4B₁₆ 27 |

28 |
29 |

30 | When in programming mode there are buttons for binary (CtrlB), octal (CtrlO) and hexadecimal (CtrlH). 31 |

32 |

33 | To set the base that results are shown in change the result format. 34 |

35 |

36 | To change the base of the current result use a base button or CtrlD to show in decimal form. 37 |

38 |
39 | -------------------------------------------------------------------------------- /src/math-variable-popup.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008-2011 Robert Ancell 3 | * 4 | * This program is free software: you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation, either version 2 of the License, or (at your option) any later 7 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 8 | * license. 9 | */ 10 | 11 | #ifndef MATH_VARIABLE_POPUP_H 12 | #define MATH_VARIABLE_POPUP_H 13 | 14 | #include 15 | #include "math-equation.h" 16 | 17 | G_BEGIN_DECLS 18 | 19 | #define MATH_VARIABLE_POPUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), math_variable_popup_get_type(), MathVariablePopup)) 20 | 21 | typedef struct MathVariablePopupPrivate MathVariablePopupPrivate; 22 | 23 | typedef struct 24 | { 25 | GtkWindow parent_instance; 26 | MathVariablePopupPrivate *priv; 27 | } MathVariablePopup; 28 | 29 | typedef struct 30 | { 31 | GtkWindowClass parent_class; 32 | } MathVariablePopupClass; 33 | 34 | GType math_variable_popup_get_type(void); 35 | 36 | MathVariablePopup *math_variable_popup_new(MathEquation *equation); 37 | 38 | G_END_DECLS 39 | 40 | #endif /* MATH_VARIABLE_POPUP_H */ 41 | -------------------------------------------------------------------------------- /src/math-preferences.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008-2011 Robert Ancell 3 | * 4 | * This program is free software: you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation, either version 2 of the License, or (at your option) any later 7 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 8 | * license. 9 | */ 10 | 11 | #ifndef MATH_PREFERENCES_H 12 | #define MATH_PREFERENCES_H 13 | 14 | #include 15 | #include 16 | #include "math-equation.h" 17 | 18 | G_BEGIN_DECLS 19 | 20 | #define MATH_PREFERENCES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), math_preferences_get_type(), MathPreferencesDialog)) 21 | 22 | typedef struct MathPreferencesDialogPrivate MathPreferencesDialogPrivate; 23 | 24 | typedef struct 25 | { 26 | GtkDialog parent_instance; 27 | MathPreferencesDialogPrivate *priv; 28 | } MathPreferencesDialog; 29 | 30 | typedef struct 31 | { 32 | GtkDialogClass parent_class; 33 | } MathPreferencesDialogClass; 34 | 35 | GType math_preferences_get_type(void); 36 | 37 | MathPreferencesDialog *math_preferences_dialog_new(MathEquation *equation); 38 | 39 | G_END_DECLS 40 | 41 | #endif /* MATH_PREFERENCES_H */ 42 | -------------------------------------------------------------------------------- /src/math-display.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008-2011 Robert Ancell 3 | * 4 | * This program is free software: you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation, either version 2 of the License, or (at your option) any later 7 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 8 | * license. 9 | */ 10 | 11 | #ifndef MATH_DISPLAY_H 12 | #define MATH_DISPLAY_H 13 | 14 | #include 15 | #include 16 | 17 | #include "math-equation.h" 18 | 19 | G_BEGIN_DECLS 20 | 21 | #define MATH_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), math_display_get_type(), MathDisplay)) 22 | 23 | typedef struct MathDisplayPrivate MathDisplayPrivate; 24 | 25 | typedef struct 26 | { 27 | GtkViewport parent_instance; 28 | MathDisplayPrivate *priv; 29 | } MathDisplay; 30 | 31 | typedef struct 32 | { 33 | GtkViewportClass parent_class; 34 | } MathDisplayClass; 35 | 36 | GType math_display_get_type(void); 37 | 38 | MathDisplay *math_display_new(void); 39 | 40 | MathDisplay *math_display_new_with_equation(MathEquation *equation); 41 | 42 | MathEquation *math_display_get_equation(MathDisplay *display); 43 | 44 | G_END_DECLS 45 | 46 | #endif /* MATH_DISPLAY_H */ 47 | -------------------------------------------------------------------------------- /po/LINGUAS: -------------------------------------------------------------------------------- 1 | # please keep this list sorted alphabetically 2 | # 3 | af 4 | am 5 | ar 6 | as 7 | ast 8 | az 9 | be 10 | bg 11 | bn 12 | bn_IN 13 | br 14 | bs 15 | ca 16 | ca@valencia 17 | cmn 18 | crh 19 | cs 20 | cy 21 | da 22 | de 23 | dz 24 | el 25 | en_AU 26 | en_CA 27 | en_GB 28 | eo 29 | es 30 | es_AR 31 | es_CL 32 | es_CO 33 | es_CR 34 | es_DO 35 | es_EC 36 | es_ES 37 | es_MX 38 | es_NI 39 | es_PA 40 | es_PE 41 | es_PR 42 | es_SV 43 | es_UY 44 | es_VE 45 | et 46 | eu 47 | fa 48 | fi 49 | fr 50 | fr_CA 51 | frp 52 | fur 53 | fy 54 | ga 55 | gl 56 | gu 57 | ha 58 | he 59 | hi 60 | hr 61 | hu 62 | hy 63 | id 64 | ie 65 | ig 66 | is 67 | it 68 | ja 69 | ka 70 | kab 71 | kk 72 | km 73 | kn 74 | ko 75 | ks 76 | ku 77 | ku_IQ 78 | ky 79 | li 80 | lt 81 | lv 82 | mai 83 | mg 84 | mi 85 | mk 86 | ml 87 | mn 88 | mr 89 | ms 90 | my 91 | nb 92 | nds 93 | ne 94 | nl 95 | nn 96 | nso 97 | oc 98 | or 99 | pa 100 | pl 101 | pms 102 | ps 103 | pt 104 | pt_BR 105 | ro 106 | ru 107 | rw 108 | si 109 | sk 110 | sl 111 | sq 112 | sr 113 | sr@latin 114 | sv 115 | ta 116 | te 117 | th 118 | tk 119 | tr 120 | tt 121 | ug 122 | uk 123 | ur 124 | uz 125 | vi 126 | wa 127 | xh 128 | yi 129 | yo 130 | zh_CN 131 | zh_HK 132 | zh_TW 133 | zu 134 | -------------------------------------------------------------------------------- /src/mate-calc.about: -------------------------------------------------------------------------------- 1 | [About] 2 | Authors=Abel McClendon ;Adam Erdman ;Alexander von Gluck IV ;Alexei Sorokin ;Allan Nordhøy ;Christopher Fujino ;Clement Lefebvre ;Friedel Wolff ;JP Cimalando ;Klaus Niederkrüger ;Laszlo Boros ;Laurent Napias ;Marcel Dijkstra ;Mark Thomas ;Martin Wimpress ;Michael Terry ;Mike Gabriel ;Nikolay Martynov ;Pablo Barciela ;Perberos ;Piotr Drąg ;Rich Burridge ;Robert Ancell ;Robert Buj ;Sander Sweers ;Scott Balneaves ;Sorokin Alexei ;Stefan Tauner ;Stefano Karapetsas ;Stephen Krauth ;Steve Zesch ;Victor Kareh ;Vlad Orlov ;Wolfgang Ulbrich ;Wu Xiaotian ; 3 | -------------------------------------------------------------------------------- /help/C/equation.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 0 8 | 9 | 10 | 11 | Basic Equations 12 | 13 |

14 | Equations are entered in standard mathematical form. 15 | For example to add 7 and 2 enter the following: 16 |

17 | 18 |

19 | 7+2 20 |

21 |
22 |

23 | To solve, press the = button with your mouse or the Enter key on your keyboard. 24 |

25 |

26 | Calculations are performed in mathematical order - multiplication and division are performed before addition and subtraction. 27 | The following equation solves to 1 (3×2 = 6, 7−6 = 1). 28 |

29 | 30 |

31 | 7−3×2 32 |

33 |
34 |

35 | To change the order of calculation use parenthesis. 36 | The following equation solves to 8 (7−3 = 4, 4×2 = 8). 37 |

38 | 39 |

40 | (7−3)×2 41 |

42 |
43 |

44 | To clear the display press the Clr button or Escape. 45 |

46 |
47 | -------------------------------------------------------------------------------- /help/Makefile.am: -------------------------------------------------------------------------------- 1 | @YELP_HELP_RULES@ 2 | HELP_ID = mate-calc 3 | HELP_FILES = absolute.page \ 4 | base.page \ 5 | boolean.page \ 6 | complex.page \ 7 | conv-base.page \ 8 | conv-character.page \ 9 | conv-currency.page \ 10 | conv-length.page \ 11 | conv-time.page \ 12 | conv-weight.page \ 13 | equation.page \ 14 | factorial.page \ 15 | factorize.page \ 16 | financial.page \ 17 | functions.page \ 18 | index.page \ 19 | keyboard.page \ 20 | legal.xml \ 21 | logarithm.page \ 22 | modulus.page \ 23 | mouse.page \ 24 | number-display.page \ 25 | percentage.page \ 26 | power.page \ 27 | scientific.page \ 28 | superscript.page \ 29 | trigonometry.page \ 30 | variables.page 31 | 32 | # Add linguas to be ignored, e.g. IGNORE_HELP_LINGUAS = ca de es fr 33 | IGNORE_HELP_LINGUAS = 34 | HELP_LINGUAS = $(if $(IGNORE_HELP_LINGUAS), \ 35 | $(filter-out $(IGNORE_HELP_LINGUAS),$(subst /,,$(dir $(wildcard */*.po)))), \ 36 | $(subst /,,$(dir $(wildcard */*.po))) ) 37 | 38 | DISTCLEANFILES = \ 39 | Makefile.in 40 | 41 | -include $(top_srcdir)/git.mk 42 | -------------------------------------------------------------------------------- /help/C/trigonometry.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | Trigonometry 10 | 11 |

12 | Trigonometry can be performed using the sin, cos, and tan function. 13 |

14 | 15 |

16 | sin 45 17 |

18 |
19 |

20 | The angle units used can be changed from the CalculatorPreferences menu. 21 | Trigonometry buttons are visible when in Advanced mode. 22 |

23 |

24 | Hyperbolic functions are available by adding "h" to the end of a function. 25 |

26 | 27 |

28 | sinh 0.34 29 |

30 |
31 |

32 | Inverse functions are entered either using the inverse symbol ⁻¹ (CtrlI) or the "a" form of the function. 33 | The following two equations are equivalent. 34 |

35 | 36 |

37 | sin⁻¹ 0.5 38 |

39 |

40 | asin 0.5 41 |

42 |
43 |

44 | To enter π with the keyboard use CtrlP. 45 |

46 |
47 | -------------------------------------------------------------------------------- /src/lexer.h: -------------------------------------------------------------------------------- 1 | #ifndef LEXER_H 2 | #define LEXER_H 3 | 4 | #include "prelexer.h" 5 | 6 | /* Structure to hold single token. */ 7 | typedef struct 8 | { 9 | gchar* string; /* Poniter to local copy of token string. */ 10 | guint start_index; /* Start index in original stream. */ 11 | guint end_index; /* End index in original stream. */ 12 | LexerTokenType token_type; /* Type of token. */ 13 | } LexerToken; 14 | 15 | /* Structure to hold lexer state and all the tokens. */ 16 | typedef struct 17 | { 18 | PreLexerState *prelexer; /* Pre-lexer state. Pre-lexer is part of lexer. */ 19 | LexerToken *tokens; /* Pointer to the dynamic array of LexerTokens. */ 20 | guint token_count; /* Count of tokens in array. */ 21 | guint next_token; /* Index of next, to be sent, token. */ 22 | struct parser_state *parent; /* Pointer to the parent parser. */ 23 | } LexerState; 24 | 25 | /* Create a new LexerState object and fill the dynamic array with tokens. */ 26 | LexerState* l_create_lexer(const gchar*, struct parser_state*); 27 | 28 | /* Destroy LexerState object and free up space. */ 29 | void l_destroy_lexer(LexerState*); 30 | 31 | /* Tokanize complete string. */ 32 | void l_insert_all_tokens(LexerState*); 33 | 34 | /* Return next, to be sent, token. */ 35 | LexerToken* l_get_next_token(LexerState*); 36 | 37 | /* Roll back one token. */ 38 | void l_roll_back(LexerState*); 39 | 40 | #endif /* LEXER_H */ 41 | -------------------------------------------------------------------------------- /help/C/power.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | Powers and Roots 10 | 11 |

12 | Powers are entered by putting a superscript number after the value. 13 |

14 | 15 |

16 | 5² 17 |

18 |
19 |

20 | The inverse of a number can be entered using the inverse symbol ⁻¹ (CtrlI). 21 |

22 | 23 |

24 | 3⁻¹ 25 |

26 |
27 |

28 | Powers can also be calculated using the ^ symbol. 29 | This allows the power to be an equation. 30 |

31 | 32 |

33 | 5^(6−2) 34 |

35 |
36 |

37 | If your keyboard does not have a ^ key you can use * twice. 38 |

39 |

40 | Square roots can be calculated using the symbol (CtrlR). 41 |

42 | 43 |

44 | √2 45 |

46 |
47 |

48 | n-th roots can be calculated by putting a subscript number before the root sign. 49 |

50 | 51 |

52 | ₃√2 53 |

54 |
55 |
56 | -------------------------------------------------------------------------------- /help/C/complex.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | Complex Numbers 10 | 11 |

12 | MATE Calculator supports complex numbers, as well as the following functions while in Advanced mode. 13 |

14 | 15 | 16 | 17 | 18 | 19 | 26 | 27 | 28 | 29 | 30 | 37 | 38 | 39 | 40 | 41 | 48 | 49 | 50 | 51 | 52 | 59 | 60 | 61 |

Re

Returns the real part of a complex number. For example:

20 | 21 |

22 | Re (2-5i) = 2 23 |

24 |
25 |

Im

Returns the imaginary part of a complex number. For example:

31 | 32 |

33 | Im (2-5i) = -5 34 |

35 |
36 |

conj

Returns the conjugate of a complex number. For example:

42 | 43 |

44 | conj (2-5i) = 2+5i 45 |

46 |
47 |

Arg

Returns the argument of a complex number. For example:

53 | 54 |

55 | Arg (2-5i) = -68.1986 56 |

57 |
58 |
62 | 63 | 64 |
65 | -------------------------------------------------------------------------------- /src/math-variables.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008-2011 Robert Ancell 3 | * 4 | * This program is free software: you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation, either version 2 of the License, or (at your option) any later 7 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 8 | * license. 9 | */ 10 | 11 | #ifndef MATH_VARIABLES_H 12 | #define MATH_VARIABLES_H 13 | 14 | #include 15 | #include "mp.h" 16 | 17 | G_BEGIN_DECLS 18 | 19 | #define MATH_VARIABLES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), math_equation_get_type(), MathVariables)) 20 | 21 | typedef struct MathVariablesPrivate MathVariablesPrivate; 22 | 23 | typedef struct 24 | { 25 | GObject parent_instance; 26 | MathVariablesPrivate *priv; 27 | } MathVariables; 28 | 29 | typedef struct 30 | { 31 | GObjectClass parent_class; 32 | } MathVariablesClass; 33 | 34 | GType math_variables_get_type(void); 35 | 36 | MathVariables *math_variables_new(void); 37 | 38 | gchar **math_variables_get_names(MathVariables *variables); 39 | 40 | void math_variables_set(MathVariables *variables, const char *name, const MPNumber *value); 41 | 42 | MPNumber *math_variables_get(MathVariables *variables, const char *name); 43 | 44 | void math_variables_delete(MathVariables *variables, const char *name); 45 | 46 | G_END_DECLS 47 | 48 | #endif /* MATH_VARIABLES_H */ 49 | -------------------------------------------------------------------------------- /src/currency-manager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008-2011 Robert Ancell. 3 | * 4 | * This program is free software: you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation, either version 2 of the License, or (at your option) any later 7 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 8 | * license. 9 | */ 10 | 11 | #ifndef CURRENCY_MANAGER_H 12 | #define CURRENCY_MANAGER_H 13 | 14 | #include "currency.h" 15 | #include "mp.h" 16 | 17 | G_BEGIN_DECLS 18 | 19 | #define CURRENCY_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), currency_manager_get_type(), CurrencyManager)) 20 | 21 | typedef struct CurrencyManagerPrivate CurrencyManagerPrivate; 22 | 23 | typedef struct 24 | { 25 | GObject parent_instance; 26 | CurrencyManagerPrivate *priv; 27 | } CurrencyManager; 28 | 29 | typedef struct 30 | { 31 | GObjectClass parent_class; 32 | void (*updated)(CurrencyManager *manager); 33 | } CurrencyManagerClass; 34 | 35 | GType currency_manager_get_type(void); 36 | 37 | CurrencyManager *currency_manager_get_default(void); 38 | 39 | GList *currency_manager_get_currencies(CurrencyManager *manager); 40 | 41 | Currency *currency_manager_get_currency(CurrencyManager *manager, const gchar *name); 42 | 43 | const MPNumber *currency_manager_get_value(CurrencyManager *manager, const gchar *currency); 44 | 45 | G_END_DECLS 46 | 47 | #endif /* CURRENCY_MANAGER_H */ 48 | -------------------------------------------------------------------------------- /src/org.mate.calculator.gresource.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | buttons-advanced.ui 21 | buttons-basic.ui 22 | buttons-financial.ui 23 | buttons-programming.ui 24 | mate-calc.about 25 | preferences.ui 26 | history-entry.ui 27 | 28 | 29 | -------------------------------------------------------------------------------- /help/C/number-display.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | Result Format 10 | 11 |

12 | The format used to display results can be changed from the CalculatorPreferences menu. 13 |

14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |

Decimal

Results are displayed as decimal numbers

Scientific

Results are displayed in scientific notation

Engineering

Results are displayed in scientific notation except the exponent is always a multiple of three

Binary

Results are displayed as binary numbers

Octal

Results are displayed as octal numbers

Hexadecimal

Results are displayed as hexadecimal numbers

40 |

41 | The number of decimal places, if trailing zeroes and if thousands separators are shown can also be configured. 42 |

43 |
44 | -------------------------------------------------------------------------------- /help/C/variables.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | Variables 10 | 11 |

12 | To assign a value to a variable use the = symbol or choose the variable to assign to with the x button in advanced mode. 13 | A variable name must only contain upper or lower characters. 14 |

15 | 16 |

17 | x=5 18 |

19 |

20 | value=82 21 |

22 |
23 |

24 | Variables can be used in any equation and are substituted for their assigned value. 25 | Variables can be inserted using the x button. 26 |

27 | 28 |

29 | 6x+3 30 |

31 |

32 | xy−3x+7y−21 33 |

34 |
35 |

36 | The following variables are always defined. 37 |

38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 |

ans

Result of previous calculation

e

Euler's Number

π

Pi

rand

Random value in the range [0,1] (changes on each read)

56 |
57 | -------------------------------------------------------------------------------- /src/math-buttons.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008-2011 Robert Ancell 3 | * 4 | * This program is free software: you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation, either version 2 of the License, or (at your option) any later 7 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 8 | * license. 9 | */ 10 | 11 | #ifndef MATH_BUTTONS_H 12 | #define MATH_BUTTONS_H 13 | 14 | #include 15 | #include 16 | #include "math-equation.h" 17 | 18 | G_BEGIN_DECLS 19 | 20 | #define MATH_BUTTONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), math_buttons_get_type(), MathButtons)) 21 | 22 | typedef struct MathButtonsPrivate MathButtonsPrivate; 23 | 24 | typedef struct 25 | { 26 | GtkVBox parent_instance; 27 | MathButtonsPrivate *priv; 28 | } MathButtons; 29 | 30 | typedef struct 31 | { 32 | GtkVBoxClass parent_class; 33 | } MathButtonsClass; 34 | 35 | typedef enum { 36 | BASIC, 37 | ADVANCED, 38 | FINANCIAL, 39 | PROGRAMMING 40 | } ButtonMode; 41 | 42 | GType math_buttons_get_type(void); 43 | 44 | MathButtons *math_buttons_new(MathEquation *equation); 45 | 46 | void math_buttons_set_mode(MathButtons *buttons, ButtonMode mode); 47 | 48 | ButtonMode math_buttons_get_mode(MathButtons *buttons); 49 | 50 | void math_buttons_set_programming_base(MathButtons *buttons, gint base); 51 | 52 | gint math_buttons_get_programming_base(MathButtons *buttons); 53 | 54 | G_END_DECLS 55 | 56 | #endif /* MATH_BUTTONS_H */ 57 | -------------------------------------------------------------------------------- /src/currency.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008-2011 Robert Ancell. 3 | * 4 | * This program is free software: you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation, either version 2 of the License, or (at your option) any later 7 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 8 | * license. 9 | */ 10 | 11 | #ifndef CURRENCY_H 12 | #define CURRENCY_H 13 | 14 | #include 15 | #include "mp.h" 16 | 17 | G_BEGIN_DECLS 18 | 19 | #define CURRENCY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), currency_get_type(), Currency)) 20 | 21 | typedef struct CurrencyPrivate CurrencyPrivate; 22 | 23 | typedef struct 24 | { 25 | GObject parent_instance; 26 | CurrencyPrivate *priv; 27 | } Currency; 28 | 29 | typedef struct 30 | { 31 | GObjectClass parent_class; 32 | } CurrencyClass; 33 | 34 | GType currency_get_type(void); 35 | 36 | Currency *currency_new(const gchar *name, 37 | const gchar *display_name, 38 | const gchar *symbol); 39 | 40 | const gchar *currency_get_name(Currency *currency); 41 | 42 | const gchar *currency_get_short_display_name(Currency *currency); 43 | 44 | const gchar *currency_get_display_name(Currency *currency); 45 | 46 | const gchar *currency_get_symbol(Currency *currency); 47 | 48 | void currency_set_value(Currency *currency, MPNumber *value); 49 | 50 | const MPNumber *currency_get_value(Currency *currency); 51 | 52 | G_END_DECLS 53 | 54 | #endif /* CURRENCY_H */ 55 | -------------------------------------------------------------------------------- /data/mate-calc.appdata.xml.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | mate-calc.desktop 5 | CC0-1.0 6 | GPL-2.0+ 7 | MATE Calc 8 | MATE Desktop calculator 9 | 10 |

11 | MATE Calc is a powerful graphical calculator with financial, 12 | logical and scientific modes. It uses a multiple precision package 13 | to do its arithmetic to give a high degree of accuracy. 14 |

15 |

16 | MATE Calc is a fork of GNOME Calc and part of the MATE Desktop Environment. 17 | If you would like to know more about MATE and MATE Calc, please visit the 18 | project's home page. 19 |

20 |
21 | 22 | 23 | 24 | https://alexpl.fedorapeople.org/AppData/mate-calc/screens/mate-calc_01.png 25 | 26 | 27 | 28 | 29 | https://alexpl.fedorapeople.org/AppData/mate-calc/screens/mate-calc_02.png 30 | 31 | 32 | 33 | 34 | https://alexpl.fedorapeople.org/AppData/mate-calc/screens/mate-calc_03.png 35 | 36 | 37 | 38 | http://www.mate-desktop.org 39 | mate-dev@ml.mate-desktop.org 40 | MATE 41 |
42 | -------------------------------------------------------------------------------- /help/C/superscript.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | _ 8 | 9 | 10 | 11 | Superscript and Subscript 12 | 13 |

14 | Some equations may require numbers to be entered in superscript or subscript form. e.g. 15 |

16 | 17 |

18 | 19 | 20 | 21 | x 22 | 3 23 | 24 | + 25 | 26 | 2 27 | 28 | x 29 | 2 30 | 31 | 32 | - 33 | 5 34 | 35 | 36 |

37 |
38 |

39 | To enter superscript numbers with the mouse select the number mode using the ↑n and ↓n buttons. 40 | When one of these modes is active clicking the number buttons will enter numbers in superscript or subscript. 41 | To return to normal number mode click the active button. 42 |

43 |

44 | To enter superscript numbers with the keyboard hold down Ctrl while entering the number. 45 | Hold Alt for subscript. 46 |

47 |

48 | The number mode returns to normal when entering the next non-number character (e.g. +). 49 |

50 |
51 | -------------------------------------------------------------------------------- /src/math-history-entry.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020-2021 MATE developers 3 | * 4 | * This program is free software: you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation, either version 2 of the License, or (at your option) any later 7 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 8 | * license. 9 | * 10 | * 11 | */ 12 | 13 | #ifndef MATH_HISTORY_ENTRY_VIEW_H 14 | #define MATH_HISTORY_ENTRY_VIEW_H 15 | 16 | #include 17 | #include 18 | 19 | #include "math-display.h" 20 | #include "math-history.h" 21 | 22 | G_BEGIN_DECLS 23 | 24 | #define MATH_HISTORY_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), math_history_entry_get_type(), MathHistoryEntry)) 25 | 26 | typedef struct MathHistoryEntryPrivate MathHistoryEntryPrivate; 27 | 28 | typedef struct 29 | { 30 | GtkListBoxRow parent_instance; 31 | MathHistoryEntryPrivate *priv; 32 | } MathHistoryEntry; 33 | 34 | typedef struct 35 | { 36 | GtkListBoxRowClass parent_class; 37 | } MathHistoryEntryClass; 38 | 39 | GType math_history_entry_get_type(void); 40 | 41 | MathHistoryEntry * 42 | math_history_entry_new(MathEquation *equation); 43 | 44 | void 45 | math_history_entry_insert_entry(MathHistoryEntry *history_entry, const gchar *equation, MPNumber *answer, MpSerializer *serializer); 46 | 47 | void 48 | math_history_entry_redisplay(MathHistoryEntry *history_entry, MpSerializer *serializer); 49 | 50 | gchar * 51 | math_history_entry_get_equation(MathHistoryEntry *history_entry); 52 | 53 | G_END_DECLS 54 | 55 | #endif /* MATH_HISTORY_ENTRY_VIEW_H */ 56 | -------------------------------------------------------------------------------- /src/math-converter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008-2011 Robert Ancell 3 | * 4 | * This program is free software: you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation, either version 2 of the License, or (at your option) any later 7 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 8 | * license. 9 | */ 10 | 11 | #ifndef MATH_CONVERTER_H 12 | #define MATH_CONVERTER_H 13 | 14 | #include 15 | #include 16 | 17 | #include "math-equation.h" 18 | #include "unit.h" 19 | 20 | G_BEGIN_DECLS 21 | 22 | #define MATH_CONVERTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), math_converter_get_type(), MathConverter)) 23 | 24 | typedef struct MathConverterPrivate MathConverterPrivate; 25 | 26 | typedef struct 27 | { 28 | GtkHBox parent_instance; 29 | MathConverterPrivate *priv; 30 | } MathConverter; 31 | 32 | typedef struct 33 | { 34 | GtkHBoxClass parent_class; 35 | 36 | void (*changed)(MathConverter *converter); 37 | } MathConverterClass; 38 | 39 | GType math_converter_get_type(void); 40 | 41 | MathConverter *math_converter_new(MathEquation *equation); 42 | 43 | void math_converter_set_category(MathConverter *converter, const gchar *category); 44 | 45 | const gchar *math_converter_get_category(MathConverter *converter); 46 | 47 | void math_converter_set_conversion(MathConverter *converter, /*const gchar *category,*/ const gchar *unit_a, const gchar *unit_b); 48 | 49 | void math_converter_get_conversion(MathConverter *converter, Unit **from_unit, Unit **to_unit); 50 | 51 | G_END_DECLS 52 | 53 | #endif /* MATH_CONVERTER_H */ 54 | -------------------------------------------------------------------------------- /src/unit.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1987-2008 Sun Microsystems, Inc. All Rights Reserved. 3 | * Copyright (C) 2008-2011 Robert Ancell. 4 | * 5 | * This program is free software: you can redistribute it and/or modify it under 6 | * the terms of the GNU General Public License as published by the Free Software 7 | * Foundation, either version 2 of the License, or (at your option) any later 8 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 9 | * license. 10 | */ 11 | 12 | #ifndef UNIT_H 13 | #define UNIT_H 14 | 15 | #include 16 | #include "mp.h" 17 | 18 | G_BEGIN_DECLS 19 | 20 | #define UNIT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), unit_get_type(), Unit)) 21 | 22 | typedef struct UnitPrivate UnitPrivate; 23 | 24 | typedef struct 25 | { 26 | GObject parent_instance; 27 | UnitPrivate *priv; 28 | } Unit; 29 | 30 | typedef struct 31 | { 32 | GObjectClass parent_class; 33 | } UnitClass; 34 | 35 | GType unit_get_type(void); 36 | 37 | Unit *unit_new(const gchar *name, 38 | const gchar *display_name, 39 | const gchar *format, 40 | const gchar *from_function, 41 | const gchar *to_function, 42 | const gchar *symbols); 43 | 44 | const gchar *unit_get_name(Unit *unit); 45 | 46 | const gchar *unit_get_display_name(Unit *unit); 47 | 48 | gboolean unit_matches_symbol(Unit *unit, const gchar *symbol); 49 | 50 | const GList *unit_get_symbols(Unit *unit); 51 | 52 | gboolean unit_convert_from(Unit *unit, const MPNumber *x, MPNumber *z); 53 | 54 | gboolean unit_convert_to(Unit *unit, const MPNumber *x, MPNumber *z); 55 | 56 | gchar *unit_format(Unit *unit, MPNumber *x); 57 | 58 | G_END_DECLS 59 | 60 | #endif /* UNIT_H */ 61 | -------------------------------------------------------------------------------- /src/parserfunc.h: -------------------------------------------------------------------------------- 1 | #ifndef PARSERFUNC_H 2 | #define PARSERFUNC_H 3 | 4 | #include "parser.h" 5 | 6 | void set_error(ParserState*, gint, const gchar*); 7 | 8 | void* pf_none(ParseNode*); 9 | 10 | void* pf_set_var(ParseNode*); 11 | 12 | void* pf_convert_number(ParseNode*); 13 | 14 | void* pf_convert_1(ParseNode*); 15 | 16 | gchar* pf_make_unit(gchar* source, gchar* power); 17 | 18 | void* pf_get_variable(ParseNode*); 19 | 20 | void* pf_get_variable_with_power(ParseNode*); 21 | 22 | void* pf_apply_func(ParseNode*); 23 | 24 | void* pf_apply_func_with_power(ParseNode*); 25 | 26 | void* pf_apply_func_with_npower(ParseNode*); 27 | 28 | void* pf_do_nth_root(ParseNode*); 29 | 30 | void* pf_do_sqrt(ParseNode*); 31 | 32 | void* pf_do_root_3(ParseNode*); 33 | 34 | void* pf_do_root_4(ParseNode*); 35 | 36 | void* pf_do_floor(ParseNode*); 37 | 38 | void* pf_do_ceiling(ParseNode*); 39 | 40 | void* pf_do_round(ParseNode*); 41 | 42 | void* pf_do_fraction(ParseNode*); 43 | 44 | void* pf_do_abs(ParseNode*); 45 | 46 | void* pf_do_x_pow_y(ParseNode*); 47 | 48 | void* pf_do_x_pow_y_int(ParseNode*); 49 | 50 | void* pf_do_factorial(ParseNode*); 51 | 52 | void* pf_unary_minus(ParseNode*); 53 | 54 | void* pf_do_divide(ParseNode*); 55 | 56 | void* pf_do_mod(ParseNode*); 57 | 58 | void* pf_do_multiply(ParseNode*); 59 | 60 | void* pf_do_subtract(ParseNode*); 61 | 62 | void* pf_do_add(ParseNode*); 63 | 64 | void* pf_do_add_percent(ParseNode*); 65 | 66 | void* pf_do_subtract_percent(ParseNode*); 67 | 68 | void* pf_do_percent(ParseNode*); 69 | 70 | void* pf_do_not(ParseNode*); 71 | 72 | void* pf_do_and(ParseNode*); 73 | 74 | void* pf_do_or(ParseNode*); 75 | 76 | void* pf_do_xor(ParseNode*); 77 | 78 | void* pf_constant(ParseNode*); 79 | 80 | #endif /* PARSERFUNC_H */ 81 | -------------------------------------------------------------------------------- /src/math-history.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020-2021 MATE developers 3 | * 4 | * This program is free software: you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation, either version 2 of the License, or (at your option) any later 7 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 8 | * license. 9 | * 10 | * 11 | */ 12 | 13 | #ifndef MATH_HISTORY_VIEW_H 14 | #define MATH_HISTORY_VIEW_H 15 | 16 | #include 17 | #include 18 | 19 | #include "math-history-entry.h" 20 | #include "math-display.h" 21 | #include "math-equation.h" 22 | 23 | G_BEGIN_DECLS 24 | 25 | #define MATH_HISTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), math_history_get_type(), MathHistory)) 26 | 27 | typedef struct MathHistoryPrivate MathHistoryPrivate; 28 | 29 | typedef struct 30 | { 31 | GtkScrolledWindow parent_instance; 32 | MathHistoryPrivate *priv; 33 | } MathHistory; 34 | 35 | typedef struct 36 | { 37 | GtkScrolledWindowClass parent_class; 38 | } MathHistoryClass; 39 | 40 | GType math_history_get_type(void); 41 | 42 | MathHistory * 43 | math_history_new(MathEquation *equation); 44 | 45 | void 46 | math_history_insert_entry(MathHistory *history, char *equation, MPNumber *answer); 47 | 48 | gpointer 49 | math_history_get_entry_at(MathHistory *history, int index); 50 | 51 | void 52 | math_history_set_current(MathHistory *history, int value); 53 | 54 | int 55 | math_history_get_current(MathHistory *history); 56 | 57 | void 58 | math_history_clear(MathHistory *history); 59 | 60 | void 61 | math_history_set_serializer(MathHistory *history, MpSerializer *serializer); 62 | 63 | G_END_DECLS 64 | 65 | #endif /* MATH_HISTORY_VIEW_H */ 66 | -------------------------------------------------------------------------------- /src/unit-manager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1987-2008 Sun Microsystems, Inc. All Rights Reserved. 3 | * Copyright (C) 2008-2011 Robert Ancell. 4 | * 5 | * This program is free software: you can redistribute it and/or modify it under 6 | * the terms of the GNU General Public License as published by the Free Software 7 | * Foundation, either version 2 of the License, or (at your option) any later 8 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 9 | * license. 10 | */ 11 | 12 | #ifndef UNIT_MANAGER_H 13 | #define UNIT_MANAGER_H 14 | 15 | #include 16 | #include "unit-category.h" 17 | #include "mp.h" 18 | 19 | G_BEGIN_DECLS 20 | 21 | #define UNIT_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), unit_manager_get_type(), UnitManager)) 22 | 23 | typedef struct UnitManagerPrivate UnitManagerPrivate; 24 | 25 | typedef struct 26 | { 27 | GObject parent_instance; 28 | UnitManagerPrivate *priv; 29 | } UnitManager; 30 | 31 | typedef struct 32 | { 33 | GObjectClass parent_class; 34 | } UnitManagerClass; 35 | 36 | GType unit_manager_get_type(void); 37 | 38 | UnitManager *unit_manager_get_default(void); 39 | 40 | UnitCategory *unit_manager_add_category(UnitManager *manager, const gchar *name, const gchar *display_name); 41 | 42 | const GList *unit_manager_get_categories(UnitManager *manager); 43 | 44 | UnitCategory *unit_manager_get_category(UnitManager *manager, const gchar *category); 45 | 46 | Unit *unit_manager_get_unit_by_name(UnitManager *manager, const gchar *name); 47 | 48 | Unit *unit_manager_get_unit_by_symbol(UnitManager *manager, const gchar *symbol); 49 | 50 | gboolean unit_manager_convert_by_symbol(UnitManager *manager, const MPNumber *x, const char *x_symbol, const char *z_symbol, MPNumber *z); 51 | 52 | G_END_DECLS 53 | 54 | #endif /* UNIT_MANAGER_H */ 55 | -------------------------------------------------------------------------------- /src/unit-category.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1987-2008 Sun Microsystems, Inc. All Rights Reserved. 3 | * Copyright (C) 2008-2011 Robert Ancell. 4 | * 5 | * This program is free software: you can redistribute it and/or modify it under 6 | * the terms of the GNU General Public License as published by the Free Software 7 | * Foundation, either version 2 of the License, or (at your option) any later 8 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 9 | * license. 10 | */ 11 | 12 | #ifndef UNIT_CATEGORY_H 13 | #define UNIT_CATEGORY_H 14 | 15 | #include 16 | #include "unit.h" 17 | #include "mp.h" 18 | 19 | G_BEGIN_DECLS 20 | 21 | #define UNIT_CATEGORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), unit_category_get_type(), UnitCategory)) 22 | 23 | typedef struct UnitCategoryPrivate UnitCategoryPrivate; 24 | 25 | typedef struct 26 | { 27 | GObject parent_instance; 28 | UnitCategoryPrivate *priv; 29 | } UnitCategory; 30 | 31 | typedef struct 32 | { 33 | GObjectClass parent_class; 34 | } UnitCategoryClass; 35 | 36 | GType unit_category_get_type(void); 37 | 38 | UnitCategory *unit_category_new(const gchar *name, const gchar *display_name); 39 | 40 | const gchar *unit_category_get_name(UnitCategory *category); 41 | 42 | const gchar *unit_category_get_display_name(UnitCategory *category); 43 | 44 | Unit *unit_category_get_unit_by_name(UnitCategory *category, const gchar *name); 45 | 46 | Unit *unit_category_get_unit_by_symbol(UnitCategory *category, const gchar *symbol); 47 | 48 | void unit_category_add_unit(UnitCategory *category, Unit *unit); 49 | 50 | const GList *unit_category_get_units(UnitCategory *category); 51 | 52 | gboolean unit_category_convert(const UnitCategory *category, const MPNumber *x, Unit *x_units, Unit *z_units, MPNumber *z); 53 | 54 | G_END_DECLS 55 | 56 | #endif /* UNIT_CATEGORY_H */ 57 | -------------------------------------------------------------------------------- /src/math-window.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1987-2008 Sun Microsystems, Inc. All Rights Reserved. 3 | * Copyright (C) 2008-2011 Robert Ancell. 4 | * 5 | * This program is free software: you can redistribute it and/or modify it under 6 | * the terms of the GNU General Public License as published by the Free Software 7 | * Foundation, either version 2 of the License, or (at your option) any later 8 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 9 | * license. 10 | */ 11 | 12 | #ifndef MATH_WINDOW_H 13 | #define MATH_WINDOW_H 14 | 15 | #include 16 | #include "math-equation.h" 17 | #include "math-display.h" 18 | #include "math-buttons.h" 19 | #include "math-preferences.h" 20 | 21 | G_BEGIN_DECLS 22 | 23 | #define MATH_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), math_window_get_type(), MathWindow)) 24 | 25 | typedef struct MathWindowPrivate MathWindowPrivate; 26 | 27 | typedef struct 28 | { 29 | GtkWindow parent_instance; 30 | MathWindowPrivate *priv; 31 | } MathWindow; 32 | 33 | typedef struct 34 | { 35 | GtkWindowClass parent_class; 36 | 37 | void (*quit) (MathWindow *window); 38 | } MathWindowClass; 39 | 40 | GType math_window_get_type(void); 41 | 42 | MathWindow *math_window_new(MathEquation *equation); 43 | 44 | GtkWidget *math_window_get_menu_bar(MathWindow *window); 45 | 46 | MathEquation *math_window_get_equation(MathWindow *window); 47 | 48 | MathDisplay *math_window_get_display(MathWindow *window); 49 | 50 | MathButtons *math_window_get_buttons(MathWindow *window); 51 | 52 | gboolean math_window_get_show_history(MathWindow *window); 53 | 54 | void math_window_set_show_history(MathWindow *window, gboolean visible); 55 | 56 | void math_window_critical_error(MathWindow *window, const gchar *title, const gchar *contents); 57 | 58 | G_END_DECLS 59 | 60 | #endif /* MATH_WINDOW_H */ 61 | -------------------------------------------------------------------------------- /data/mate-calc.1: -------------------------------------------------------------------------------- 1 | .\" Man page for mate-calc 2 | .TH MATE-CALC 1 "1 February 2014" "MATE Desktop Environment" 3 | .\" Please adjust this date when revising the manpage. 4 | .\" 5 | .SH "NAME" 6 | mate-calc \- (mate-calculator) \- The MATE Desktop Environment Calculator 7 | .SH "SYNOPSIS" 8 | .B mate-calc [OPTIONS...] [FILES...] 9 | .SH "DESCRIPTION" 10 | \fBmate-calc\fR is the official calculator for the MATE Desktop Environment. It has been designed to be used with either the mouse or the keyboard. It is visually similar to a lot of hand-held calculators. 11 | .PP 12 | This manual page briefly documents the \fBmate-calc\fR command. 13 | .SH "OPTIONS" 14 | .TP 15 | \fB\-s, \-\-solve\fR 16 | Solve the equation provided following this option. 17 | .TP 18 | \fB\-\-version\fR 19 | Output version information and exit. 20 | .TP 21 | \fB\-h, \-?, \-\-help\fR 22 | Print standard command line options. 23 | .TP 24 | \fB\-\-help\-all\fR 25 | Print all command line options. 26 | .P 27 | This program also accepts the standard GTK options. 28 | .SH "EXAMPLES" 29 | \fBmate-calc \-s 4*10.5\fR 30 | .RS 4 31 | Multiply 4 by 10.5 32 | .RE 33 | .PP 34 | \fBmate-calc \-s 21+21\fR 35 | .RS 4 36 | Add 21 plus 21 37 | .RE 38 | .PP 39 | \fBmate-calc \-\-solve '((5.25×4)×2)'\fR 40 | .RS 4 41 | Multiply 5.25 by 4 and their product by 2 42 | .RE 43 | .PP 44 | \fBmate-calc 45 | .RS 4 46 | Open the Calculator GUI. 47 | .SH "BUGS" 48 | .SS Should you encounter any bugs, they may be reported at: 49 | http://github.com/mate-desktop/mate-calc/issues 50 | .SH "AUTHORS" 51 | .SS This Man Page has been written for the MATE Desktop Environment by: 52 | Adam Erdman (2014) 53 | .SH "SEE ALSO" 54 | .SS 55 | mate-calc documentation can be found from the "Help" menu, or by pressing the F1 key. 56 | Further information may also be available at: http://wiki.mate-desktop.org/docs 57 | .P 58 | .BR mate-calc-cmd (1) 59 | -------------------------------------------------------------------------------- /.github/workflows/notify.yml: -------------------------------------------------------------------------------- 1 | name: Notifications 2 | 3 | on: 4 | push: 5 | branches: [ master, main ] 6 | tags: [ 'v*' ] 7 | workflow_run: 8 | workflows: ["Build and Test"] 9 | types: 10 | - completed 11 | 12 | jobs: 13 | irc-notify: 14 | runs-on: ubuntu-latest 15 | if: > 16 | (github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/'))) || 17 | (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'failure') 18 | 19 | steps: 20 | - name: Send IRC notification on success 21 | if: > 22 | (github.event_name == 'push') || 23 | (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') 24 | uses: Gottox/irc-message-action@v2 25 | continue-on-error: true 26 | with: 27 | server: irc.libera.chat 28 | channel: '#mate-dev' 29 | nickname: mate-github-bot 30 | message: | 31 | [mate-calc] ${{ github.actor }}: ${{ github.event.head_commit.message || 'Workflow completed successfully' }} 32 | [${{ github.ref_name }}] ${{ github.sha }} Success ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} 33 | 34 | - name: Send IRC notification on failure 35 | if: github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'failure' 36 | uses: Gottox/irc-message-action@v2 37 | continue-on-error: true 38 | with: 39 | server: irc.libera.chat 40 | channel: '#mate-dev' 41 | nickname: mate-github-bot 42 | message: | 43 | [mate-calc] Build failed: ${{ github.event.workflow_run.head_commit.message }} 44 | [${{ github.event.workflow_run.head_branch }}] ${{ github.event.workflow_run.head_sha }} Failure ${{ github.event.workflow_run.html_url }} -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('mate-calc','c', 2 | version: '1.28.0', 3 | meson_version: '>=0.50.0', 4 | license: 'GPLv3+', 5 | ) 6 | 7 | i18n = import('i18n') 8 | gnome = import('gnome') 9 | 10 | po_dir = join_paths(meson.source_root(), 'po') 11 | datadir = join_paths([ get_option('prefix'),get_option('datadir') ]) 12 | pkgdatadir = join_paths([ get_option('prefix'),get_option('datadir'),'mate-calc' ]) 13 | bindir = join_paths([ get_option('prefix'), 'bin' ]) 14 | schemadir = join_paths([ datadir, 'glib-2.0', 'schemas' ]) 15 | locale_dir = join_paths(get_option('prefix'), get_option('localedir')) 16 | 17 | # Dependencies 18 | glib_min_version = '2.40.0' 19 | 20 | gio = dependency('gio-2.0', version: '>= ' + glib_min_version) 21 | glib = dependency('glib-2.0', version: '>= ' + glib_min_version) 22 | gobject = dependency('gobject-2.0', version: '>= ' + glib_min_version) 23 | libxml = dependency('libxml-2.0') 24 | gtk = dependency('gtk+-3.0', version : '>=3.22') 25 | 26 | # Libraries 27 | cc = meson.get_compiler('c') 28 | mpc = declare_dependency( 29 | dependencies: [ 30 | cc.find_library('mpc'), 31 | ] 32 | ) 33 | mpfr = declare_dependency( 34 | dependencies: [ 35 | cc.find_library('mpfr'), 36 | ] 37 | ) 38 | conf = configuration_data() 39 | 40 | top_inc = include_directories('.') 41 | 42 | conf.set('G_LOG_USE_STRUCTURED', true) 43 | conf.set_quoted('PACKAGE_NAME', 'mate-calc') 44 | conf.set_quoted('PACKAGE_VERSION', meson.project_version()) 45 | conf.set_quoted('VERSION', meson.project_version()) 46 | conf.set_quoted('GETTEXT_PACKAGE', 'mate-calc') 47 | conf.set_quoted('PACKAGE_URL', 'https://mate-desktop.org') 48 | conf.set_quoted('DATADIR', datadir) 49 | conf.set_quoted('UI_DIR', join_paths([pkgdatadir,'uidir'])) 50 | conf.set_quoted('PKGDATADIR', pkgdatadir) 51 | conf.set_quoted('LOCALE_DIR', join_paths([ get_option('prefix'), 52 | get_option('datadir'), 53 | 'locale' ])) 54 | 55 | conf.set_quoted('pkgdatadir', pkgdatadir) 56 | conf.set_quoted('bindir', bindir) 57 | 58 | configure_file(output : 'config.h', configuration : conf) 59 | 60 | subdir('src') 61 | subdir('data') 62 | subdir('po') 63 | subdir('help') 64 | 65 | meson.add_install_script('meson-postinstall.sh') 66 | -------------------------------------------------------------------------------- /help/C/keyboard.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | Using the Keyboard 10 | 11 |

12 | All mathematical equations can be entered using the keyboard. 13 |

14 |

15 | The following key combinations can be used to enter keys that may not be available on your keyboard. 16 |

17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |

×

*

÷

/

^

* twice

CtrlR

π

CtrlP

39 |

40 | To enter superscript numbers use Ctrlnumber, for subscript use Altnumber. 41 |

42 |

43 | When in programming mode, to cycle between base digits use: 44 |

45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |

Binary

CtrlB

Octal

CtrlO

Decimal

CtrlD

Hexadecimal

CtrlH

63 |

64 | To cycle between history entries you may use: 65 |

66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 |

Previous Entry

AltUp

Next Entry

AltDown

76 |
77 | -------------------------------------------------------------------------------- /src/mp-equation.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2004-2008 Sami Pietila 3 | * Copyright (C) 2008-2011 Robert Ancell. 4 | * 5 | * This program is free software: you can redistribute it and/or modify it under 6 | * the terms of the GNU General Public License as published by the Free Software 7 | * Foundation, either version 2 of the License, or (at your option) any later 8 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 9 | * license. 10 | */ 11 | 12 | #ifndef MP_EQUATION_H 13 | #define MP_EQUATION_H 14 | 15 | #include "mp.h" 16 | 17 | typedef enum 18 | { 19 | PARSER_ERR_NONE = 0, 20 | PARSER_ERR_INVALID, 21 | PARSER_ERR_OVERFLOW, 22 | PARSER_ERR_UNKNOWN_VARIABLE, 23 | PARSER_ERR_UNKNOWN_FUNCTION, 24 | PARSER_ERR_UNKNOWN_CONVERSION, 25 | PARSER_ERR_MP 26 | } MPErrorCode; 27 | 28 | /* Options for parser */ 29 | typedef struct { 30 | /* Default number base */ 31 | int base; 32 | 33 | /* The wordlength for binary operations in bits (e.g. 8, 16, 32) */ 34 | int wordlen; 35 | 36 | /* Units for angles (e.g. radians, degrees) */ 37 | MPAngleUnit angle_units; 38 | 39 | // FIXME: 40 | // int enable_builtins; 41 | 42 | /* Data to pass to callbacks */ 43 | void *callback_data; 44 | 45 | /* Function to check if a variable is defined */ 46 | int (*variable_is_defined)(const char *name, void *data); 47 | 48 | /* Function to get variable values */ 49 | int (*get_variable)(const char *name, MPNumber *z, void *data); 50 | 51 | /* Function to set variable values */ 52 | void (*set_variable)(const char *name, const MPNumber *x, void *data); 53 | 54 | /* Function to check if a function is defined */ 55 | int (*function_is_defined)(const char *name, void *data); 56 | 57 | /* Function to solve functions */ 58 | int (*get_function)(const char *name, const MPNumber *x, MPNumber *z, void *data); 59 | 60 | /* Function to convert units */ 61 | int (*convert)(const MPNumber *x, const char *x_units, const char *z_units, MPNumber *z, void *data); 62 | } MPEquationOptions; 63 | 64 | MPErrorCode mp_equation_parse(const char *expression, MPEquationOptions *options, MPNumber *result, char **error_token); 65 | const char *mp_error_code_to_string(MPErrorCode error_code); 66 | 67 | int sub_atoi(const char *data); 68 | int super_atoi(const char *data); 69 | #endif 70 | -------------------------------------------------------------------------------- /src/parser.h: -------------------------------------------------------------------------------- 1 | #ifndef PARSER_H 2 | #define PARSER_H 3 | 4 | #include 5 | 6 | #include "mp-equation.h" 7 | #include "mp.h" 8 | 9 | /* Operator Associativity. */ 10 | typedef enum 11 | { 12 | LEFT_ASSOCIATIVE, 13 | RIGHT_ASSOCIATIVE 14 | } Associativity; 15 | 16 | /* Operator Precedence. */ 17 | typedef enum 18 | { 19 | P_Unknown = 0, 20 | P_AddSubtract=1, 21 | P_Multiply=2, 22 | P_Mod=3, 23 | P_Divide=4, 24 | P_Not=5, 25 | P_Root=6, 26 | P_Function=7, 27 | P_Boolean=8, 28 | P_Percentage=9, 29 | /* UnaryMinus and Power must have same precedence. */ 30 | P_UnaryMinus=10, 31 | P_Power=10, 32 | P_Factorial=11, 33 | P_NumberVariable=12, 34 | /* P_Depth should be always at the bottom. It stops node jumping off the current depth level. */ 35 | P_Depth 36 | } Precedence; 37 | 38 | /* ParseNode structure for parse tree. */ 39 | typedef struct parse_node 40 | { 41 | struct parse_node *parent; 42 | struct parse_node *left, *right; 43 | LexerToken *token; 44 | guint precedence; 45 | Associativity associativity; 46 | void* value; 47 | struct parser_state* state; 48 | void* (*evaluate) (struct parse_node* self); 49 | } ParseNode; 50 | 51 | /* ParserState structure. Stores parser state. */ 52 | typedef struct parser_state 53 | { 54 | ParseNode *root; 55 | ParseNode *right_most; 56 | LexerState *lexer; 57 | guint depth_level; 58 | MPEquationOptions *options; 59 | int error; 60 | char *error_token; 61 | MPNumber ret; 62 | int (*variable_is_defined)(struct parser_state *state, const char *name); 63 | int (*get_variable)(struct parser_state *state, const char *name, MPNumber *z); 64 | void (*set_variable)(struct parser_state *state, const char *name, const MPNumber *x); 65 | int (*function_is_defined)(struct parser_state *state, const char *name); 66 | int (*get_function)(struct parser_state *state, const char *name, const MPNumber *x, MPNumber *z); 67 | int (*convert)(struct parser_state *state, const MPNumber *x, const char *x_units, const char *z_units, MPNumber *z); 68 | } ParserState; 69 | 70 | /* Create ParserState object. */ 71 | ParserState* p_create_parser(const gchar*, MPEquationOptions*); 72 | 73 | /* Destroy ParserState object. */ 74 | void p_destroy_parser(ParserState*); 75 | 76 | /* Parse string from ParserState. */ 77 | guint p_parse(ParserState*); 78 | 79 | #endif /* PARSER_H */ 80 | -------------------------------------------------------------------------------- /src/currency.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008-2011 Robert Ancell. 3 | * 4 | * This program is free software: you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation, either version 2 of the License, or (at your option) any later 7 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 8 | * license. 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | #include "currency.h" 15 | #include "mp-serializer.h" 16 | #include "currency-manager.h" // FIXME: Move out of here 17 | 18 | struct CurrencyPrivate 19 | { 20 | gchar *name; 21 | gchar *display_name; 22 | gchar *symbol; 23 | MPNumber value; 24 | }; 25 | 26 | G_DEFINE_TYPE_WITH_PRIVATE (Currency, currency, G_TYPE_OBJECT); 27 | 28 | Currency * 29 | currency_new(const gchar *name, 30 | const gchar *display_name, 31 | const gchar *symbol) 32 | { 33 | Currency *currency = g_object_new(currency_get_type(), NULL); 34 | 35 | currency->priv->name = g_strdup(name); 36 | currency->priv->display_name = g_strdup(display_name); 37 | currency->priv->symbol = g_strdup(symbol); 38 | currency->priv->value = mp_new(); 39 | 40 | return currency; 41 | } 42 | 43 | const gchar * 44 | currency_get_name(Currency *currency) 45 | { 46 | g_return_val_if_fail (currency != NULL, NULL); 47 | return currency->priv->name; 48 | } 49 | 50 | const gchar * 51 | currency_get_display_name(Currency *currency) 52 | { 53 | g_return_val_if_fail (currency != NULL, NULL); 54 | return currency->priv->display_name; 55 | } 56 | 57 | const gchar * 58 | currency_get_symbol(Currency *currency) 59 | { 60 | g_return_val_if_fail (currency != NULL, NULL); 61 | return currency->priv->symbol; 62 | } 63 | 64 | void 65 | currency_set_value(Currency *currency, MPNumber *value) 66 | { 67 | g_return_if_fail (currency != NULL); 68 | g_return_if_fail (value != NULL); 69 | mp_set_from_mp (value, ¤cy->priv->value); 70 | } 71 | 72 | const MPNumber * 73 | currency_get_value(Currency *currency) 74 | { 75 | g_return_val_if_fail (currency != NULL, NULL); 76 | return ¤cy->priv->value; 77 | } 78 | 79 | static void 80 | currency_class_init(CurrencyClass *klass) 81 | { 82 | } 83 | 84 | static void 85 | currency_init(Currency *currency) 86 | { 87 | currency->priv = currency_get_instance_private (currency); 88 | } 89 | -------------------------------------------------------------------------------- /src/mp-equation-private.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2004-2008 Sami Pietila 2 | * Copyright (c) 2008-2009 Robert Ancell 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2, or (at your option) 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 | * 02110-1301, USA. 18 | */ 19 | 20 | #ifndef MP_EQUATION_PRIVATE_H 21 | #define MP_EQUATION_PRIVATE_H 22 | 23 | #include "mp-equation.h" 24 | 25 | /* An opaque pointer. */ 26 | #ifndef YY_TYPEDEF_YY_SCANNER_T 27 | #define YY_TYPEDEF_YY_SCANNER_T 28 | typedef void* yyscan_t; 29 | #endif /* YY_TYPEDEF_YY_SCANNER_T */ 30 | 31 | typedef struct MPEquationParserState MPEquationParserState; 32 | 33 | /* State for parser */ 34 | struct MPEquationParserState { 35 | /* User provided options */ 36 | MPEquationOptions* options; 37 | 38 | /* Function to check if a variable is defined */ 39 | int (*variable_is_defined)(MPEquationParserState* state, const char* name); 40 | 41 | /* Function to get variable values */ 42 | int (*get_variable)(MPEquationParserState* state, const char* name, MPNumber* z); 43 | 44 | /* Function to set variable values */ 45 | void (*set_variable)(MPEquationParserState* state, const char* name, const MPNumber *x); 46 | 47 | /* Function to check if a function is defined */ 48 | int (*function_is_defined)(MPEquationParserState* state, const char* name); 49 | 50 | /* Function to solve functions */ 51 | int (*get_function)(MPEquationParserState* state, const char* name, const MPNumber* x, MPNumber* z); 52 | 53 | /* Function to convert units */ 54 | int (*convert)(MPEquationParserState* state, const MPNumber* x, const char* x_units, const char* z_units, MPNumber* z); 55 | 56 | // FIXME: get_operator?? 57 | 58 | /* Error returned from parser */ 59 | int error; 60 | 61 | /* Name of token where error occured */ 62 | char* error_token; 63 | 64 | /* Value returned from parser */ 65 | MPNumber ret; 66 | }; 67 | 68 | int _mp_equation_error(void* yylloc, MPEquationParserState* state, char* text); 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MATE Calculator 2 | 3 | ![mate-calc-icon](mate-calc.png) 4 | 5 | ## General Information 6 | 7 | MATE Calculator (*mate-calc*) started as a fork of *gnome-calc*, the calculator application 8 | that was previously in the OpenWindows Deskset of the Solaris 8 9 | operating system. 10 | 11 | ## Calctool history 12 | 13 | Calctool was a project I worked on before I joined the OpenWindows 14 | DeskSet engineering group at Sun. It was originally released to 15 | comp.sources.unix in the late 1980's, and worked with many different 16 | graphics packages including SunView, X11, Xview, NeWS and MGR. There 17 | was also a version that worked on dumb tty terminals. 18 | 19 | It used a double-precision maths library that was a combination of the 20 | work of Fred Fish and various routines that were in the BSD 4.3 maths 21 | library. 22 | 23 | A lot of people in the community provided feedback in the form of 24 | comments, bug reports and fixes. In 1990, I started working in the 25 | DeskSet engineering group. I was working for Sun Microsystems in 26 | Australia at the time, (having moved there from England in 1983). 27 | 28 | I searched around looking for multiple precision maths libraries and 29 | found a package called MP written in FORTRAN by Richard Brent. I 30 | converted it to C, adjusted the glue between the resultant code and the 31 | calctool code, and this went on to be the basis of the calculator that 32 | was in the OpenWindows DeskSet. I also added scientific, financial and 33 | logical modes. This calctool was also the basis of the dtcalc 34 | application that is a part of CDE (albeit I had nothing to do with 35 | that). 36 | 37 | With its inclusion in the MATE CVS repository, it was renamed to 38 | *mate-calc*. 39 | 40 | More recently, Sami Pietila provided arithmetic precedence support and 41 | Robert Ancell converted the UI to use Glade. 42 | 43 | ## Build/Installation 44 | 45 | MATE Calculator requires GTK+ (>= 3.22) and the [GNU MPFR](https://www.mpfr.org/) and [GNU MPC](http://www.multiprecision.org/mpc) libraries. For a complete list of dependencies see the [build.yml](https://github.com/mate-desktop/mate-calc/blob/master/.build.yml). 46 | 47 | Simple install procedure: 48 | 49 | ``` 50 | $ ./autogen.sh # Build configuration 51 | $ make # Build 52 | [ Become root if necessary ] 53 | $ make install # Installation 54 | ``` 55 | 56 | 57 | ## Acknowledgements 58 | 59 | See the [AUTHORS](https://github.com/mate-desktop/mate-calc/blob/master/AUTHORS) file. 60 | 61 | Suggestions for further improvement would be most welcome, plus bug 62 | reports and comments. 63 | 64 | The Mate Team. -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | MATE: 2 | Perberos 3 | Steve Zesch 4 | Stefano Karapetsas 5 | 6 | GNOME: 7 | Glade support/Main maintainer: Robert Ancell 8 | Original author/maintainer: Rich Burridge 9 | Arithmetic precedence support: Sami Pietila 10 | 11 | ---- 12 | 13 | The maths library used by mate-calc is based on the freely available MP 14 | multi-precision floating-point arithmetic package originally written in 15 | FORTRAN by Richard Brent in the 1970's, when he was with the Computer 16 | Centre, Australian National University. 17 | 18 | It has been converted from FORTRAN into C using the freely available 19 | f2c translator, available via netlib on research.att.com. 20 | 21 | The subsequently converted C code has then been tidied up, mainly to 22 | remove any dependencies on the libI77 and libF77 support libraries. 23 | 24 | More information on this MP package can be found at: 25 | 26 | ACM Paper: 27 | 28 | http://web.comlab.ox.ac.uk/oucl/work/richard.brent/pd/rpb042.pdf 29 | 30 | User Guide: 31 | 32 | http://web.comlab.ox.ac.uk/oucl/work/richard.brent/pd/rpb035.pdf 33 | 34 | Source Code: 35 | 36 | http://web.comlab.ox.ac.uk/oucl/work/richard.brent/ftp/rpb043/rpb043.tar.gz 37 | 38 | ---- 39 | 40 | Acknowledgements for the GNOME/Gtk+ version: 41 | 42 | Dennis Cranston and Andrew Sobala for various bug fixes. 43 | Calum Benson for HCI advice. 44 | Breda McColgan for online help. 45 | Evan Martin for help with the menu buttons. 46 | Gregory Merchan for the calctool_display_frame 47 | custom widget. 48 | 49 | ---- 50 | 51 | Acknowledgements from the previous versions (circa 1990): 52 | 53 | Thanks to Ed Falk at Sun Microsystems (Mountain View) for most of the 54 | basic arithmetical algorithms used, to Andrew Nicholson for revising the 55 | previous version of the NeWS code, to Sriram Ramachandran for fixing up 56 | the XView code, to Hala Abdalla for the original implementation of the 57 | popup menu and function keyboard support, to Didier Poirot for the 58 | calctool Imakefiles, and to Sisira Jayasinghe for better error detecting 59 | addition, subtraction, multiplication and division routines for the 60 | maths library. 61 | 62 | Thanks go also to James Buster, David Weaver, Steve Damron, Mike Bender, 63 | Charles Tierney, Trevor Watson, Marla Berg, David Hough, Jeff Donsbach, 64 | Mel Melchner, Peter Allott, Skip Gilbrech, Tom Friedel, Keith McNeill 65 | Stephen Frede, Johan Vromans, David Karr, Steve Alexander, Gary Bartlett, 66 | Steve Nahm, Daniel Yang and Rick Stevenson for bug reports and/or bug fixes 67 | plus sugggested enhancements. 68 | -------------------------------------------------------------------------------- /src/mate-calc-cmd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 Rich Burridge 3 | * 4 | * This program is free software: you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation, either version 2 of the License, or (at your option) any later 7 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 8 | * license. 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "mp-equation.h" 19 | #include "mp-serializer.h" 20 | 21 | #define MAXLINE 1024 22 | 23 | static MpSerializer *result_serializer; 24 | 25 | static void 26 | solve(const char *equation) 27 | { 28 | int ret; 29 | MPEquationOptions options; 30 | MPNumber z = mp_new(); 31 | gchar *result_str = NULL; 32 | 33 | memset(&options, 0, sizeof(options)); 34 | options.base = 10; 35 | options.wordlen = 32; 36 | options.angle_units = MP_DEGREES; 37 | 38 | ret = mp_equation_parse(equation, &options, &z, NULL); 39 | 40 | if (ret == PARSER_ERR_MP) 41 | fprintf(stderr, "Error %s\n", mp_get_error()); 42 | else if (ret) 43 | fprintf(stderr, "Error %d\n", ret); 44 | else { 45 | result_str = mp_serializer_to_string(result_serializer, &z); 46 | printf("%s\n", result_str); 47 | } 48 | g_free(result_str); 49 | mp_clear(&z); 50 | } 51 | 52 | /* Adjust user input equation string before solving it. */ 53 | static void 54 | str_adjust(char *str) 55 | { 56 | int i, j = 0; 57 | 58 | str[strlen(str)-1] = '\0'; /* Remove newline at end of string. */ 59 | for (i = 0; str[i] != '\0'; i++) { /* Remove whitespace. */ 60 | if (str[i] != ' ' && str[i] != '\t') 61 | str[j++] = str[i]; 62 | } 63 | str[j] = '\0'; 64 | if (j > 0 && str[j-1] == '=') /* Remove trailing '=' (if present). */ 65 | str[j-1] = '\0'; 66 | } 67 | 68 | int 69 | main(void) 70 | { 71 | char *equation, *line; 72 | 73 | /* Seed random number generator. */ 74 | srand48((long) time((time_t *) 0)); 75 | 76 | setlocale(LC_ALL, ""); 77 | 78 | result_serializer = mp_serializer_new(MP_DISPLAY_FORMAT_AUTOMATIC, 10, 9); 79 | 80 | equation = (char *) malloc(MAXLINE * sizeof(char)); 81 | while (1) { 82 | printf("> "); 83 | line = fgets(equation, MAXLINE, stdin); 84 | 85 | if (line != NULL) 86 | str_adjust(equation); 87 | 88 | if (line == NULL || strcmp(equation, "exit") == 0 || strcmp(equation, "quit") == 0 || strlen(equation) == 0) 89 | break; 90 | 91 | solve(equation); 92 | } 93 | free(equation); 94 | 95 | return 0; 96 | } 97 | -------------------------------------------------------------------------------- /help/C/functions.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | Functions 10 | 11 |

12 | Functions can be used by inserting the name of the function followed by the function argument. 13 | If the argument is not a number or variable then use parenthesis around the argument. 14 |

15 | 16 |

17 | sin 30 18 |

19 |

20 | abs (5−9) 21 |

22 |
23 |

24 | The following functions are defined. 25 |

26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 |

abs

Absolute Value

cos

Cosine

cosh

Hyperbolic Cosine

erf

Gauss Error function

frac

Fractional Component

int

Integer Component

ln

Natural Logarithm

log

Logarithm

not

Boolean NOT

ones

Ones complement

sin

Sine

sinh

Hyperbolic Sine

sqrt

Square Root

tan

Tangent

tanh

Hyperbolic Tangent

twos

Twos complement

zeta

Riemann zeta function

96 |

97 | MATE Calculator does not support user-defined functions. 98 |

99 |
100 | -------------------------------------------------------------------------------- /help/C/financial.page: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | Financial Functions 10 |

11 | When in financial mode the following buttons are available. 12 |

13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 |

Ctrm

Calculate the number of compounding periods necessary to increase an investment of present value to a future value, at a fixed interest rate per compounding period.

Ddb

Calculate the depreciation allowance on an asset for a specified period of time, using the double-declining balance method.

Fv

Calculate the future value of an investment based on a series of equal payments at a periodic interest rate over the number of payment periods in the term.

Gpm

Calculate the resale price of a product, based on the product cost and the wanted gross profit margin.

Pmt

Calculate the amount of the periodic payment of a loan, where payments are made at the end of each payment period.

Pv

Calculate the present value of an investment based on a series of equal payments discounted at a periodic interest rate over the number of payment periods in the term.

Rate

Calculate the periodic interest necessary to increase an investment to a future value, over the number of compounding periods.

Sln

Calculate the straight-line depreciation of an asset for one period. The straight-line method of depreciation divides the depreciable cost evenly over the useful life of an asset. The useful life is the number of periods, typically years, over which an asset is depreciated.

Syd

Calculate the depreciation allowance on an asset for a specified period of time, using the Sum-of-the-Years'-Digits method. This method of depreciation accelerates the rate of depreciation, so that more depreciation expense occurs in earlier periods than in later ones. The useful life is the number of periods, typically years, over which an asset is depreciated.

Term

Calculate the number of payment periods that are necessary during the term of an ordinary annuity, to accumulate a future value, at a periodic interest rate.

55 | 56 |

57 | Financial functions cannot be performed using the keyboard. 58 |

59 |
60 |
61 | -------------------------------------------------------------------------------- /src/mp-serializer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 Robin Sonefors 3 | * Copyright (C) 2008-2011 Robert Ancell. 4 | * 5 | * This program is free software: you can redistribute it and/or modify it under 6 | * the terms of the GNU General Public License as published by the Free Software 7 | * Foundation, either version 2 of the License, or (at your option) any later 8 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 9 | * license. 10 | */ 11 | 12 | #ifndef MP_SERIALIZER_H 13 | #define MP_SERIALIZER_H 14 | 15 | #include 16 | #include 17 | 18 | #include "mp.h" 19 | 20 | G_BEGIN_DECLS 21 | 22 | #define MP_TYPE_SERIALIZER (mp_serializer_get_type()) 23 | #define MP_SERIALIZER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), mp_serializer_get_type(), MpSerializer)) 24 | 25 | typedef struct MpSerializerPrivate MpSerializerPrivate; 26 | 27 | typedef struct { 28 | GObject parent; 29 | MpSerializerPrivate *priv; 30 | } MpSerializer; 31 | 32 | typedef struct { 33 | GObjectClass parent; 34 | } MpSerializerClass; 35 | 36 | /* Number display mode. */ 37 | typedef enum { 38 | MP_DISPLAY_FORMAT_AUTOMATIC, 39 | MP_DISPLAY_FORMAT_FIXED, 40 | MP_DISPLAY_FORMAT_SCIENTIFIC, 41 | MP_DISPLAY_FORMAT_ENGINEERING 42 | } MpDisplayFormat; 43 | 44 | GType mp_serializer_get_type(void); 45 | 46 | MpSerializer *mp_serializer_new(MpDisplayFormat format, int base, int trailing_digits); 47 | 48 | gchar *mp_serializer_to_string(MpSerializer *serializer, const MPNumber *z); 49 | gboolean mp_serializer_from_string(MpSerializer *serializer, const gchar *str, MPNumber *z); 50 | 51 | void mp_serializer_set_number_format(MpSerializer *serializer, MpDisplayFormat format); 52 | MpDisplayFormat mp_serializer_get_number_format(MpSerializer *serializer); 53 | 54 | void mp_serializer_set_base(MpSerializer *serializer, int base); 55 | int mp_serializer_get_base(MpSerializer *serializer); 56 | 57 | void mp_serializer_set_leading_digits(MpSerializer *serializer, int leading_digits); 58 | int mp_serializer_get_leading_digits(MpSerializer *serializer); 59 | 60 | void mp_serializer_set_trailing_digits(MpSerializer *serializer, int trailing_digits); 61 | int mp_serializer_get_trailing_digits(MpSerializer *serializer); 62 | 63 | void mp_serializer_set_radix(MpSerializer *serializer, gunichar radix); 64 | gunichar mp_serializer_get_radix(MpSerializer *serializer); 65 | 66 | void mp_serializer_set_thousands_separator(MpSerializer *serializer, gunichar separator); 67 | gunichar mp_serializer_get_thousands_separator(MpSerializer *serializer); 68 | 69 | gint mp_serializer_get_thousands_separator_count(MpSerializer *serializer); 70 | 71 | void mp_serializer_set_show_trailing_zeroes(MpSerializer *serializer, gboolean visible); 72 | gboolean mp_serializer_get_show_trailing_zeroes(MpSerializer *serializer); 73 | 74 | void mp_serializer_set_show_thousands_separators(MpSerializer *serializer, gboolean visible); 75 | gboolean mp_serializer_get_show_thousands_separators(MpSerializer *serializer); 76 | 77 | G_END_DECLS 78 | 79 | #endif /* MP_SERIALIZER_H */ 80 | -------------------------------------------------------------------------------- /src/meson.build: -------------------------------------------------------------------------------- 1 | src = [] 2 | src_cmd = [] 3 | test_mp_src = [] 4 | test_mp_eq_src = [] 5 | 6 | enums = [] 7 | 8 | enums += gnome.mkenums('types', 9 | sources: 'mp-serializer.h', 10 | c_template: 'mp-enums.c.template', 11 | h_template: 'mp-enums.h.template') 12 | 13 | ui_files = files( 14 | 'buttons-advanced.ui', 15 | 'buttons-basic.ui', 16 | 'buttons-financial.ui', 17 | 'preferences.ui' 18 | ) 19 | 20 | ui_resources = gnome.compile_resources( 21 | 'ui_resources', 22 | 'org.mate.calculator.gresource.xml', 23 | source_dir: 'src' 24 | ) 25 | 26 | src += [ 27 | 'mate-calc.c', 28 | 'currency-manager.c', 29 | 'currency.c', 30 | 'financial.c', 31 | 'lexer.c', 32 | 'math-buttons.c', 33 | 'math-converter.c', 34 | 'math-display.c', 35 | 'math-equation.c', 36 | 'math-history.c', 37 | 'math-history-entry.c', 38 | 'math-preferences.c', 39 | 'math-variable-popup.c', 40 | 'math-variables.c', 41 | 'math-window.c', 42 | 'mp-binary.c', 43 | 'mp-convert.c', 44 | 'mp-equation.c', 45 | 'mp-trigonometric.c', 46 | 'mp-serializer.c', 47 | 'mp.c', 48 | 'parser.c', 49 | 'parserfunc.c', 50 | 'prelexer.c', 51 | 'unit-category.c', 52 | 'unit-manager.c', 53 | 'unit.c', 54 | enums, 55 | ui_resources 56 | ] 57 | 58 | src_cmd += [ 59 | 'mate-calc-cmd.c', 60 | 'currency.c', 61 | 'currency-manager.c', 62 | 'mp.c', 63 | 'mp-binary.c', 64 | 'mp-convert.c', 65 | 'mp-equation.c', 66 | 'mp-serializer.c', 67 | 'mp-trigonometric.c', 68 | 'unit.c', 69 | 'unit-category.c', 70 | 'unit-manager.c', 71 | 'prelexer.c', 72 | 'lexer.c', 73 | 'parserfunc.c', 74 | 'parser.c', 75 | enums 76 | ] 77 | 78 | test_mp_src += [ 79 | 'test-mp.c', 80 | 'mp.c', 81 | 'mp-convert.c', 82 | 'mp-trigonometric.c' 83 | ] 84 | 85 | test_mp_eq_src += [ 86 | 'test-mp-equation.c', 87 | 'currency.c', 88 | 'currency-manager.c', 89 | 'mp.c', 90 | 'mp-convert.c', 91 | 'mp-binary.c', 92 | enums, 93 | 'mp-equation.c', 94 | 'mp-serializer.c', 95 | 'mp-trigonometric.c', 96 | 'unit.c', 97 | 'unit-category.c', 98 | 'unit-manager.c', 99 | 'prelexer.c', 100 | 'lexer.c', 101 | 'parserfunc.c', 102 | 'parser.c', 103 | ] 104 | 105 | executable('mate-calc', src, include_directories: top_inc, 106 | dependencies : [gio, glib, gobject,gtk, libxml, mpc, mpfr], 107 | link_args: '-rdynamic', 108 | install : true, 109 | install_dir : get_option('bindir')) 110 | 111 | executable('mate-calc-cmd', src_cmd, include_directories: top_inc, 112 | dependencies : [gio, libxml, mpc, mpfr], 113 | install : true, 114 | install_dir : get_option('bindir')) 115 | 116 | executable('test-mp', test_mp_src, include_directories: top_inc, 117 | dependencies : [gio, libxml, mpc, mpfr]) 118 | 119 | executable('test-mp-equation', test_mp_eq_src, include_directories: top_inc, 120 | dependencies: [gio, libxml, mpc, mpfr]) 121 | -------------------------------------------------------------------------------- /src/prelexer.h: -------------------------------------------------------------------------------- 1 | #ifndef PRE_LEXER_H 2 | #define PRE_LEXER_H 3 | 4 | #include 5 | 6 | /* Structure to store lexer state. */ 7 | typedef struct 8 | { 9 | gchar* stream; /* Pointer to the local copy of input string. */ 10 | guint length; /* Length of input string; stored to reduce calls to strlen(). */ 11 | guint next_index; /* Index of next (to be read) character from input. */ 12 | guint mark_index; /* Location, last marked. Useful for getting substrings as part of highlighting */ 13 | } PreLexerState; 14 | 15 | /* Enum for tokens generated by pre-lexer and lexer. */ 16 | typedef enum 17 | { 18 | T_UNKNOWN=0, //Unknown 19 | 20 | /* These are all Pre-Lexer tokens, returned by pre-lexer */ 21 | PL_DECIMAL, //Decimal saperator 22 | PL_DIGIT, //Decimal digit 23 | PL_HEX, //A-F of Hex digits 24 | PL_SUPER_DIGIT, //Super digits 25 | PL_SUPER_MINUS, //Super minus 26 | PL_SUB_DIGIT, //Sub digits 27 | PL_FRACTION, //Fractions 28 | PL_DEGREE, //Degree 29 | PL_MINUTE, //Minutes 30 | PL_SECOND, //10 //Seconds 31 | PL_LETTER, //Alphabets 32 | PL_EOS, //End of stream. Yay!! 33 | PL_SKIP, //Skip this symbol (whitespace or newline). 34 | 35 | /* These are all tokens, returned by Lexer. */ 36 | T_ADD, //Plus 37 | T_SUBTRACT, //Minus 38 | T_MULTIPLY, //Multiply 39 | T_DIV, //Divide (note can't use T_DIVIDE as it is defined in *BSD as an "integer divide fault" trap type value) 40 | T_MOD, //Modulus 41 | T_L_FLOOR, //Floor ( Left ) 42 | T_R_FLOOR, //20 //Floor ( Right ) 43 | T_L_CEILING, //Ceiling ( Left ) 44 | T_R_CEILING, //Ceiling ( Right ) 45 | T_ROOT, //Square root 46 | T_ROOT_3, //Cube root 47 | T_ROOT_4, //Fourth root 48 | T_NOT, //Bitwise NOT 49 | T_AND, //Bitwise AND 50 | T_OR, //Bitwise OR 51 | T_XOR, //Bitwise XOR 52 | T_IN, //30 //IN ( for converter ) 53 | T_NUMBER, //Number 54 | T_SUP_NUMBER, //Super Number 55 | T_NSUP_NUMBER, //Negative Super Number 56 | T_SUB_NUMBER, //Sub Number 57 | T_FUNCTION, //Function 58 | T_VARIABLE, //Variable name 59 | T_ASSIGN, //= 60 | T_L_R_BRACKET, //40 //( 61 | T_R_R_BRACKET, //) 62 | T_L_S_BRACKET, //[ 63 | T_R_S_BRACKET, //] 64 | T_L_C_BRACKET, //{ 65 | T_R_C_BRACKET, //} 66 | T_ABS, //| 67 | T_POWER, //^ 68 | T_FACTORIAL, //! 69 | T_PERCENTAGE //49 //% 70 | } LexerTokenType; 71 | 72 | /* Creates a scanner state. Useful when multiple scanners are in action. */ 73 | PreLexerState* pl_create_scanner(const gchar*); 74 | 75 | /* Destroy and free memory used by LexerState object. */ 76 | void pl_destroy_scanner(PreLexerState*); 77 | 78 | /* Roll back last scanned unichar. */ 79 | void pl_roll_back(PreLexerState*); 80 | 81 | /* Get validated gunichar from input stream. */ 82 | gunichar pl_get_next_gunichar(PreLexerState*); 83 | 84 | /* Set marker index. To be used for highlighting and error reporting. */ 85 | void pl_set_marker(PreLexerState*); 86 | 87 | /* Get marked substring. To be used for error reporting. */ 88 | gchar* pl_get_marked_substring(const PreLexerState*); 89 | 90 | /* Get next Pre-Lexer token from stream. */ 91 | LexerTokenType pl_get_next_token(PreLexerState*); 92 | 93 | #endif /* PRE_LEXER_H */ 94 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' 7 | 8 | jobs: 9 | release: 10 | runs-on: ubuntu-latest 11 | container: 12 | image: 'fedora:latest' 13 | 14 | steps: 15 | - name: Checkout code 16 | uses: actions/checkout@v4 17 | with: 18 | fetch-depth: 0 19 | 20 | - name: Install dependencies 21 | run: | 22 | dnf update -y 23 | dnf install -y \ 24 | autoconf-archive \ 25 | clang \ 26 | clang-analyzer \ 27 | bison \ 28 | desktop-file-utils \ 29 | flex \ 30 | gcc \ 31 | git \ 32 | gmp-devel \ 33 | gtk3 \ 34 | libmpc-devel \ 35 | libxml2-devel \ 36 | make \ 37 | mate-common \ 38 | mate-desktop-devel \ 39 | mpfr-devel \ 40 | redhat-rpm-config \ 41 | curl \ 42 | which \ 43 | sha256sum 44 | 45 | - name: Set up environment variables 46 | run: | 47 | export CPU_COUNT=$(nproc) 48 | echo "CPU_COUNT=$CPU_COUNT" >> $GITHUB_ENV 49 | echo "REPO_NAME=mate-calc" >> $GITHUB_ENV 50 | echo "OWNER_NAME=mate-desktop" >> $GITHUB_ENV 51 | 52 | - name: Generate build system 53 | run: | 54 | NOCONFIGURE=1 ./autogen.sh 55 | 56 | - name: Configure 57 | run: | 58 | ./configure --enable-compile-warnings=maximum 59 | 60 | - name: Build 61 | run: | 62 | make -j $CPU_COUNT 63 | 64 | - name: Create distribution archive 65 | run: | 66 | make distcheck 67 | 68 | - name: Generate checksums 69 | run: | 70 | for file in mate-calc-*.tar.xz; do 71 | if [ -f "$file" ]; then 72 | sha256sum "$file" > "$file.sha256" 73 | fi 74 | done 75 | 76 | - name: Notify release servers 77 | run: | 78 | # Notify MATE release servers (if configured) 79 | if [ -n "${{ secrets.RELEASE_NOTIFY_TOKEN }}" ]; then 80 | curl -X POST -H "Authorization: token ${{ secrets.RELEASE_NOTIFY_TOKEN }}" \ 81 | -d '{"tag":"${{ github.ref_name }}","repo":"mate-calc"}' \ 82 | https://release.mate-desktop.org/release || echo "Release notification failed" 83 | fi 84 | 85 | - name: Create GitHub Release 86 | uses: softprops/action-gh-release@v2 87 | with: 88 | draft: false 89 | prerelease: false 90 | generate_release_notes: true 91 | files: | 92 | mate-calc-*.tar.xz 93 | mate-calc-*.tar.xz.sha256 94 | body: | 95 | Release ${{ github.ref_name }} of MATE Calculator 96 | 97 | This release includes the source distribution archive and checksums. 98 | 99 | ## Installation 100 | 101 | Download the `mate-calc-*.tar.xz` file and verify it with the corresponding `.sha256` checksum file: 102 | 103 | ```bash 104 | sha256sum -c mate-calc-*.tar.xz.sha256 105 | ``` 106 | 107 | Then extract and build: 108 | 109 | ```bash 110 | tar -xf mate-calc-*.tar.xz 111 | cd mate-calc-* 112 | ./configure 113 | make 114 | sudo make install 115 | ``` 116 | env: 117 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | dnl Process this file with autoconf to produce a configure script. 2 | AC_PREREQ(2.62) 3 | AC_INIT([mate-calc], [1.28.0], [https://github.com/mate-desktop/mate-calc/issues], 4 | [mate-calc], [https://mate-desktop.org]) 5 | 6 | AM_INIT_AUTOMAKE([1.9 foreign no-dist-gzip dist-xz check-news]) 7 | AC_CONFIG_HEADERS(config.h) 8 | AM_MAINTAINER_MODE 9 | MATE_MAINTAINER_MODE_DEFINES 10 | m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) 11 | 12 | AC_ISC_POSIX 13 | AC_PROG_CC 14 | AC_HEADER_STDC 15 | 16 | GLIB_GSETTINGS 17 | MATE_COMPILE_WARNINGS 18 | 19 | dnl ########################################################################### 20 | dnl Dependencies 21 | dnl ########################################################################### 22 | 23 | GLIB_REQUIRED=2.50.0 24 | GIO_REQUIRED=2.36.0 25 | GTK_REQUIRED=3.22.0 26 | MPFR_REQUIRED=4.0.2 27 | 28 | PKG_CHECK_MODULES(MATE_CALC, [ 29 | gtk+-3.0 >= $GTK_REQUIRED 30 | glib-2.0 >= $GLIB_REQUIRED 31 | gio-2.0 >= $GIO_REQUIRED 32 | mpfr >= $MPFR_REQUIRED 33 | libxml-2.0 34 | gmodule-export-2.0 35 | ]) 36 | 37 | PKG_CHECK_MODULES(MATE_CALC_CMD, [ 38 | glib-2.0 >= $GLIB_REQUIRED 39 | gio-2.0 >= $GIO_REQUIRED 40 | mpfr >= $MPFR_REQUIRED 41 | libxml-2.0 42 | ]) 43 | 44 | GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0` 45 | AC_SUBST(GLIB_MKENUMS) 46 | 47 | AC_CHECK_LIB(m, log) 48 | AC_CHECK_LIB(mpc, log, [], [AC_MSG_ERROR(could not find required development libraries for MPC)], []) 49 | 50 | dnl ########################################################################### 51 | dnl Internationalization 52 | dnl ########################################################################### 53 | AM_GNU_GETTEXT_VERSION([0.19.8]) 54 | AM_GNU_GETTEXT_REQUIRE_VERSION([0.19.8]) 55 | AM_GNU_GETTEXT([external]) 56 | 57 | GETTEXT_PACKAGE=AC_PACKAGE_NAME 58 | AC_SUBST(GETTEXT_PACKAGE) 59 | AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[the gettext translation domain]) 60 | 61 | # ********************** 62 | # GLIB_COMPILE_RESOURCES 63 | # ********************** 64 | AC_ARG_VAR([GLIB_COMPILE_RESOURCES],[glib-compile-resources bin]) 65 | AC_PATH_PROG([GLIB_COMPILE_RESOURCES],[glib-compile-resources],[]) 66 | if test -z "$GLIB_COMPILE_RESOURCES"; then 67 | AC_MSG_ERROR([glib-compile-resources not found]) 68 | fi 69 | 70 | # ******* 71 | # XMLLINT 72 | # ******* 73 | AC_ARG_VAR([XMLLINT],[xmllint bin]) 74 | AC_PATH_PROG([XMLLINT],[xmllint],[]) 75 | if test -z "$XMLLINT"; then 76 | AC_MSG_ERROR([xmllint not found]) 77 | fi 78 | 79 | dnl ########################################################################### 80 | dnl Documentation 81 | dnl ########################################################################### 82 | 83 | YELP_HELP_INIT 84 | 85 | dnl ########################################################################### 86 | dnl Files to generate 87 | dnl ########################################################################### 88 | 89 | AC_CONFIG_FILES([ 90 | Makefile 91 | src/Makefile 92 | po/Makefile.in 93 | data/Makefile 94 | help/Makefile 95 | ]) 96 | AC_OUTPUT 97 | 98 | echo " 99 | Configure summary: 100 | 101 | ${PACKAGE_STRING} 102 | `echo $PACKAGE_STRING | sed "s/./=/g"` 103 | 104 | prefix: ${prefix} 105 | source code location: ${srcdir} 106 | compiler: ${CC} 107 | compiler flags: ${CFLAGS} 108 | warning flags: ${WARN_CFLAGS} 109 | " 110 | -------------------------------------------------------------------------------- /src/history-entry.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | True 7 | False 8 | 12 9 | 16 10 | 12 11 | 16 12 | True 13 | 14 | 15 | True 16 | False 17 | 18 | 19 | 20 | True 21 | False 22 | end 23 | 1 24 | 0 25 | 0.5 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 0 34 | 0 35 | 4 36 | 37 | 38 | 39 | 40 | True 41 | False 42 | = 43 | 1 44 | 0.5 45 | 0.5 46 | 47 | 48 | 49 | 50 | 51 | 52 | 4 53 | 0 54 | 55 | 56 | 57 | 58 | True 59 | False 60 | 61 | 62 | 63 | True 64 | False 65 | end 66 | 12 67 | 1 68 | 0.5 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 5 78 | 0 79 | 2 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /po/Makevars: -------------------------------------------------------------------------------- 1 | # Makefile variables for PO directory in any package using GNU gettext. 2 | 3 | # Usually the message domain is the same as the package name. 4 | DOMAIN = $(PACKAGE) 5 | 6 | # These two variables depend on the location of this directory. 7 | subdir = po 8 | top_builddir = .. 9 | 10 | # These options get passed to xgettext. 11 | XGETTEXT_OPTIONS = --from-code=UTF-8 --keyword=_ --keyword=N_ --keyword=C_:1c,2 --keyword=NC_:1c,2 --keyword=g_dngettext:2,3 --add-comments 12 | 13 | # This is the copyright holder that gets inserted into the header of the 14 | # $(DOMAIN).pot file. Set this to the copyright holder of the surrounding 15 | # package. (Note that the msgstr strings, extracted from the package's 16 | # sources, belong to the copyright holder of the package.) Translators are 17 | # expected to transfer the copyright for their translations to this person 18 | # or entity, or to disclaim their copyright. The empty string stands for 19 | # the public domain; in this case the translators are expected to disclaim 20 | # their copyright. 21 | COPYRIGHT_HOLDER = MATE Desktop Environment team 22 | 23 | # This tells whether or not to prepend "GNU " prefix to the package 24 | # name that gets inserted into the header of the $(DOMAIN).pot file. 25 | # Possible values are "yes", "no", or empty. If it is empty, try to 26 | # detect it automatically by scanning the files in $(top_srcdir) for 27 | # "GNU packagename" string. 28 | PACKAGE_GNU = 29 | 30 | # This is the email address or URL to which the translators shall report 31 | # bugs in the untranslated strings: 32 | # - Strings which are not entire sentences, see the maintainer guidelines 33 | # in the GNU gettext documentation, section 'Preparing Strings'. 34 | # - Strings which use unclear terms or require additional context to be 35 | # understood. 36 | # - Strings which make invalid assumptions about notation of date, time or 37 | # money. 38 | # - Pluralisation problems. 39 | # - Incorrect English spelling. 40 | # - Incorrect formatting. 41 | # It can be your email address, or a mailing list address where translators 42 | # can write to without being subscribed, or the URL of a web page through 43 | # which the translators can contact you. 44 | MSGID_BUGS_ADDRESS = 45 | 46 | # This is the list of locale categories, beyond LC_MESSAGES, for which the 47 | # message catalogs shall be used. It is usually empty. 48 | EXTRA_LOCALE_CATEGORIES = 49 | 50 | # This tells whether the $(DOMAIN).pot file contains messages with an 'msgctxt' 51 | # context. Possible values are "yes" and "no". Set this to yes if the 52 | # package uses functions taking also a message context, like pgettext(), or 53 | # if in $(XGETTEXT_OPTIONS) you define keywords with a context argument. 54 | USE_MSGCTXT = no 55 | 56 | # These options get passed to msgmerge. 57 | # Useful options are in particular: 58 | # --previous to keep previous msgids of translated messages, 59 | # --quiet to reduce the verbosity. 60 | MSGMERGE_OPTIONS = 61 | 62 | # These options get passed to msginit. 63 | # If you want to disable line wrapping when writing PO files, add 64 | # --no-wrap to MSGMERGE_OPTIONS, XGETTEXT_OPTIONS, and 65 | # MSGINIT_OPTIONS. 66 | MSGINIT_OPTIONS = 67 | 68 | # This tells whether or not to regenerate a PO file when $(DOMAIN).pot 69 | # has changed. Possible values are "yes" and "no". Set this to no if 70 | # the POT file is checked in the repository and the version control 71 | # program ignores timestamps. 72 | PO_DEPENDS_ON_POT = yes 73 | 74 | # This tells whether or not to forcibly update $(DOMAIN).pot and 75 | # regenerate PO files on "make dist". Possible values are "yes" and 76 | # "no". Set this to no if the POT file and PO files are maintained 77 | # externally. 78 | DIST_DEPENDS_ON_UPDATE_PO = yes 79 | -------------------------------------------------------------------------------- /data/org.mate.calc.gschema.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 9 24 | 25 | Accuracy value 26 | The number of digits displayed after the numeric point 27 | 28 | 29 | 64 30 | 31 | Word size 32 | The size of the words used in bitwise operations 33 | 34 | 35 | 10 36 | 37 | Numeric Base 38 | The numeric base 39 | 40 | 41 | false 42 | Show Thousands Separators 43 | Indicates whether thousands separators are shown in large numbers. 44 | 45 | 46 | false 47 | Show Trailing Zeroes 48 | Indicates whether any trailing zeroes after the numeric point should be shown in the display value. 49 | 50 | 51 | false 52 | Show History 53 | Shows all recent calculations 54 | 55 | 56 | 'automatic' 57 | Number format 58 | The format to display numbers in 59 | 60 | 61 | 'degrees' 62 | Angle units 63 | The angle units to use 64 | 65 | 66 | 'basic' 67 | Button mode 68 | The button mode 69 | 70 | 71 | '' 72 | Source currency 73 | Currency of the current calculation 74 | 75 | 76 | '' 77 | Target currency 78 | Currency to convert the current calculation into 79 | 80 | 81 | 'degree' 82 | Source units 83 | Units of the current calculation 84 | 85 | 86 | 'radian' 87 | Target units 88 | Units to convert the current calculation into 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /src/unit-category.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1987-2008 Sun Microsystems, Inc. All Rights Reserved. 3 | * Copyright (C) 2008-2011 Robert Ancell. 4 | * 5 | * This program is free software: you can redistribute it and/or modify it under 6 | * the terms of the GNU General Public License as published by the Free Software 7 | * Foundation, either version 2 of the License, or (at your option) any later 8 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 9 | * license. 10 | */ 11 | 12 | #include 13 | 14 | #include "unit-category.h" 15 | 16 | struct UnitCategoryPrivate 17 | { 18 | gchar *name; 19 | gchar *display_name; 20 | GList *units; 21 | }; 22 | 23 | G_DEFINE_TYPE_WITH_PRIVATE (UnitCategory, unit_category, G_TYPE_OBJECT); 24 | 25 | UnitCategory * 26 | unit_category_new(const gchar *name, const gchar *display_name) 27 | { 28 | UnitCategory *category = g_object_new(unit_category_get_type(), NULL); 29 | category->priv->name = g_strdup(name); 30 | category->priv->display_name = g_strdup(display_name); 31 | return category; 32 | } 33 | 34 | const gchar * 35 | unit_category_get_name(UnitCategory *category) 36 | { 37 | g_return_val_if_fail (category != NULL, NULL); 38 | return category->priv->name; 39 | } 40 | 41 | const gchar * 42 | unit_category_get_display_name(UnitCategory *category) 43 | { 44 | g_return_val_if_fail (category != NULL, NULL); 45 | return category->priv->display_name; 46 | } 47 | 48 | void 49 | unit_category_add_unit(UnitCategory *category, Unit *unit) 50 | { 51 | g_return_if_fail (category != NULL); 52 | g_return_if_fail (unit != NULL); 53 | category->priv->units = g_list_append(category->priv->units, g_object_ref(unit)); 54 | } 55 | 56 | Unit * 57 | unit_category_get_unit_by_name(UnitCategory *category, const gchar *name) 58 | { 59 | GList *iter; 60 | 61 | g_return_val_if_fail (category != NULL, NULL); 62 | g_return_val_if_fail (name != NULL, NULL); 63 | 64 | for (iter = category->priv->units; iter; iter = iter->next) 65 | { 66 | Unit *unit = iter->data; 67 | if (strcmp(unit_get_name(unit), name) == 0) 68 | return unit; 69 | } 70 | 71 | return NULL; 72 | } 73 | 74 | Unit * 75 | unit_category_get_unit_by_symbol(UnitCategory *category, const gchar *symbol) 76 | { 77 | GList *iter; 78 | 79 | g_return_val_if_fail (category != NULL, NULL); 80 | g_return_val_if_fail (symbol != NULL, NULL); 81 | 82 | for (iter = category->priv->units; iter; iter = iter->next) { 83 | Unit *unit = iter->data; 84 | if (unit_matches_symbol(unit, symbol)) 85 | return unit; 86 | } 87 | 88 | return NULL; 89 | } 90 | 91 | const GList * 92 | unit_category_get_units(UnitCategory *category) 93 | { 94 | g_return_val_if_fail (category != NULL, NULL); 95 | return category->priv->units; 96 | } 97 | 98 | gboolean 99 | unit_category_convert(const UnitCategory *category, const MPNumber *x, Unit *x_units, Unit *z_units, MPNumber *z) 100 | { 101 | g_return_val_if_fail (category != NULL, FALSE); 102 | g_return_val_if_fail (x_units != NULL, FALSE); 103 | g_return_val_if_fail (z_units != NULL, FALSE); 104 | g_return_val_if_fail (z != NULL, FALSE); 105 | 106 | MPNumber t = mp_new(); 107 | if (!unit_convert_from(x_units, x, &t)) 108 | { 109 | mp_clear(&t); 110 | return FALSE; 111 | } 112 | if (!unit_convert_to(z_units, &t, z)) 113 | { 114 | mp_clear(&t); 115 | return FALSE; 116 | } 117 | mp_clear(&t); 118 | return TRUE; 119 | } 120 | 121 | static void 122 | unit_category_class_init(UnitCategoryClass *klass) 123 | { 124 | } 125 | 126 | static void 127 | unit_category_init(UnitCategory *category) 128 | { 129 | category->priv = unit_category_get_instance_private (category); 130 | } 131 | -------------------------------------------------------------------------------- /update-authors.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | =pod 3 | 4 | update-authors.pl is part of mate-calc. 5 | 6 | mate-calc is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | mate-calc is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with mate-calc. If not, see . 18 | 19 | =cut 20 | use strict; 21 | use warnings; 22 | 23 | sub ReplaceAuthors { 24 | my @authors = @_; 25 | $_ eq 'Alexander ' and $_ = 'Alexander Ovchinnikov ' for @authors; 26 | $_ eq 'bl0ckeduser ' and $_ = 'Gabriel Cormier-Affleck ' for @authors; 27 | $_ eq 'Glorf ' and $_ = 'Michał Bień ' for @authors; 28 | $_ eq 'hekel ' and $_ = 'Adam Erdman ' for @authors; 29 | $_ eq 'infirit ' and $_ = 'Sander Sweers ' for @authors; 30 | $_ eq 'Jason Crain ' and $_ = 'Jason Crain ' for @authors; 31 | $_ eq 'José Aliste ' and $_ = 'José Aliste ' for @authors; 32 | $_ eq 'leigh123linux ' and $_ = 'Leigh Scott ' for @authors; 33 | $_ eq 'lyokha ' and $_ = 'Alexey Radkov ' for @authors; 34 | $_ eq 'Martin Wimpress ' and $_ = 'Martin Wimpress ' for @authors; 35 | $_ eq 'monsta ' and $_ = 'Vlad Orlov ' for @authors; 36 | $_ eq 'Monsta ' and $_ = 'Vlad Orlov ' for @authors; 37 | $_ eq 'oz123 ' and $_ = 'Oz N Tiram ' for @authors; 38 | $_ eq 'Piiit ' and $_ = 'Peter Moser ' for @authors; 39 | $_ eq 'rootavish ' and $_ = 'Avishkar Gupta ' for @authors; 40 | $_ eq 'rootavish ' and $_ = 'Avishkar Gupta ' for @authors; 41 | $_ eq 'raveit ' and $_ = 'Wolfgang Ulbrich ' for @authors; 42 | $_ eq 'raveit65 ' and $_ = 'Wolfgang Ulbrich ' for @authors; 43 | $_ eq 'raveit65 ' and $_ = 'Wolfgang Ulbrich ' for @authors; 44 | $_ eq 'rbuj ' and $_ = 'Robert Buj ' for @authors; 45 | $_ eq 'Scott Balneaves ' and $_ = 'Scott Balneaves ' for @authors; 46 | $_ eq 'Wolfgang Ulbrich ' and $_ = 'Wolfgang Ulbrich ' for @authors; 47 | return @authors; 48 | } 49 | 50 | sub GetCurrentAuthors { 51 | my @authors; 52 | open(FILE,"src/mate-calc.about") or die "Can't open src/mate-calc.about""; 53 | while () { 54 | if (/^Authors=*(.+)$/) { 55 | @authors=split(";",$1); 56 | } 57 | } 58 | close FILE; 59 | return ReplaceAuthors(@authors); 60 | } 61 | 62 | sub GetNewAuthors { 63 | my @authors = `git log --pretty="%an <%ae>" --since "2012-01-01" -- . "_.h" "_.c" | sort | uniq | sed 's/@/%/g' | sed '/^mate-i18n.*/d'`; 64 | chomp @authors; 65 | return ReplaceAuthors(@authors); 66 | } 67 | 68 | my @A = GetCurrentAuthors; 69 | my @B = GetNewAuthors; 70 | my @merged = sort { $a cmp $b } keys %{{map {($_ => 1)} (@A, @B)}}; 71 | print join(';',@merged) . ';'; 72 | -------------------------------------------------------------------------------- /src/math-history-entry.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020-2021 MATE developers 3 | * 4 | * This program is free software: you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation, either version 2 of the License, or (at your option) any later 7 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 8 | * license. 9 | * 10 | * 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include "math-history-entry.h" 18 | 19 | struct MathHistoryEntryPrivate 20 | { 21 | MathEquation *equation; 22 | 23 | MPNumber *number; 24 | GtkWidget *equation_label; 25 | GtkWidget *answer_label; 26 | }; 27 | 28 | G_DEFINE_TYPE_WITH_PRIVATE (MathHistoryEntry, math_history_entry, GTK_TYPE_LIST_BOX_ROW); 29 | 30 | #define UI_HISTORY_ENTRY_RESOURCE_PATH "/org/mate/calculator/ui/history-entry.ui" 31 | 32 | MathHistoryEntry * 33 | math_history_entry_new(MathEquation *equation) 34 | { 35 | MathHistoryEntry *history_entry = g_object_new(math_history_entry_get_type(), NULL); 36 | history_entry->priv->equation = g_object_ref(equation); 37 | return history_entry; 38 | } 39 | 40 | void answer_clicked_cb(GtkWidget *widget, GdkEventButton *eventbutton, MathHistoryEntry *history_entry); 41 | G_MODULE_EXPORT 42 | void 43 | answer_clicked_cb (GtkWidget *widget, GdkEventButton *eventbutton, MathHistoryEntry *history_entry) 44 | { 45 | const gchar *answer = gtk_widget_get_tooltip_text(history_entry->priv->answer_label); 46 | 47 | if (answer != NULL) 48 | math_equation_insert(history_entry->priv->equation, answer); 49 | } 50 | 51 | void equation_clicked_cb(GtkWidget *widget, GdkEventButton *eventbutton, MathHistoryEntry *history_entry); 52 | G_MODULE_EXPORT 53 | void 54 | equation_clicked_cb (GtkWidget *widget, GdkEventButton *eventbutton, MathHistoryEntry *history_entry) 55 | { 56 | const gchar *equation = gtk_label_get_text(GTK_LABEL(history_entry->priv->equation_label)); 57 | 58 | if (equation != NULL) 59 | math_equation_set(history_entry->priv->equation, equation); 60 | } 61 | 62 | void 63 | math_history_entry_insert_entry(MathHistoryEntry *history_entry, const gchar *equation, MPNumber *answer, MpSerializer *serializer) 64 | { 65 | #define get_widget(x) GTK_WIDGET(gtk_builder_get_object(builder, x)) 66 | 67 | GtkBuilder *builder; 68 | GtkWidget *grid; 69 | 70 | mp_set_from_mp(answer, history_entry->priv->number); 71 | 72 | builder = gtk_builder_new_from_resource(UI_HISTORY_ENTRY_RESOURCE_PATH); 73 | grid = get_widget("grid"); 74 | gtk_container_add(GTK_CONTAINER(history_entry), grid); 75 | history_entry->priv->equation_label = get_widget("equation_label"); 76 | history_entry->priv->answer_label = get_widget("answer_label"); 77 | gtk_widget_set_tooltip_text(history_entry->priv->equation_label, equation); 78 | gtk_label_set_text(GTK_LABEL(history_entry->priv->equation_label), equation); 79 | gtk_builder_connect_signals(builder, history_entry); 80 | g_object_unref(builder); 81 | 82 | #undef get_widget 83 | 84 | math_history_entry_redisplay(history_entry, serializer); 85 | } 86 | 87 | void 88 | math_history_entry_redisplay(MathHistoryEntry *history_entry, MpSerializer *serializer) 89 | { 90 | gchar *answer = mp_serializer_to_string(serializer, history_entry->priv->number); 91 | 92 | gtk_widget_set_tooltip_text(history_entry->priv->answer_label, answer); 93 | gtk_label_set_text(GTK_LABEL(history_entry->priv->answer_label), answer); 94 | 95 | g_free(answer); 96 | } 97 | 98 | gchar * 99 | math_history_entry_get_equation(MathHistoryEntry *history_entry) 100 | { 101 | return gtk_widget_get_tooltip_text(history_entry->priv->equation_label); 102 | } 103 | 104 | static void 105 | math_history_entry_finalize(GObject *object) 106 | { 107 | MathHistoryEntry *self = MATH_HISTORY_ENTRY (object); 108 | 109 | mp_free(self->priv->number); 110 | 111 | G_OBJECT_CLASS (math_history_entry_parent_class)->finalize (object); 112 | } 113 | 114 | static void 115 | math_history_entry_class_init(MathHistoryEntryClass *klass) 116 | { 117 | GObjectClass *object_class = G_OBJECT_CLASS(klass); 118 | 119 | object_class->finalize = math_history_entry_finalize; 120 | } 121 | 122 | static void 123 | math_history_entry_init(MathHistoryEntry *history_entry) 124 | { 125 | history_entry->priv = math_history_entry_get_instance_private(history_entry); 126 | history_entry->priv->number = mp_new_ptr(); 127 | } 128 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | bin_PROGRAMS = mate-calc mate-calc-cmd 2 | noinst_PROGRAMS = test-mp test-mp-equation 3 | 4 | TESTS = test-mp test-mp-equation 5 | 6 | AM_CPPFLAGS = \ 7 | -DLOCALE_DIR=\""$(localedir)"\" \ 8 | $(WARN_CFLAGS) \ 9 | $(MATE_CALC_CFLAGS) 10 | 11 | BUILT_SOURCES = \ 12 | mate-calc-resources.c \ 13 | mate-calc-resources.h 14 | 15 | nodist_mate_calc_SOURCES= $(BUILT_SOURCES) 16 | 17 | mate_calc_SOURCES = \ 18 | mate-calc.c \ 19 | currency.c \ 20 | currency.h \ 21 | currency-manager.c \ 22 | currency-manager.h \ 23 | math-buttons.c \ 24 | math-buttons.h \ 25 | math-converter.c \ 26 | math-converter.h \ 27 | math-history.c \ 28 | math-history.h \ 29 | math-history-entry.c \ 30 | math-history-entry.h \ 31 | math-display.c \ 32 | math-display.h \ 33 | math-equation.c \ 34 | math-equation.h \ 35 | math-preferences.c \ 36 | math-preferences.h \ 37 | math-variables.c \ 38 | math-variables.h \ 39 | math-variable-popup.c \ 40 | math-variable-popup.h \ 41 | math-window.c \ 42 | math-window.h \ 43 | mp.c \ 44 | mp.h \ 45 | mp-binary.c \ 46 | mp-convert.c \ 47 | mp-enums.c \ 48 | mp-enums.h \ 49 | mp-equation.c \ 50 | mp-equation.h \ 51 | mp-serializer.c \ 52 | mp-serializer.h \ 53 | mp-trigonometric.c \ 54 | financial.c \ 55 | financial.h \ 56 | unit.c \ 57 | unit.h \ 58 | unit-category.c \ 59 | unit-category.h \ 60 | unit-manager.c \ 61 | unit-manager.h \ 62 | prelexer.c \ 63 | prelexer.h \ 64 | lexer.c \ 65 | lexer.h \ 66 | parserfunc.c \ 67 | parserfunc.h \ 68 | parser.c \ 69 | parser.h \ 70 | utility.h 71 | 72 | mate_calc_LDADD = \ 73 | $(MATE_CALC_LIBS) 74 | 75 | mate_calc_cmd_SOURCES = \ 76 | mate-calc-cmd.c \ 77 | currency.c \ 78 | currency.h \ 79 | currency-manager.c \ 80 | currency-manager.h \ 81 | mp.c \ 82 | mp-binary.c \ 83 | mp-convert.c \ 84 | mp-enums.c \ 85 | mp-enums.h \ 86 | mp-equation.c \ 87 | mp-serializer.c \ 88 | mp-serializer.h\ 89 | mp-trigonometric.c \ 90 | unit.c \ 91 | unit.h \ 92 | unit-category.c \ 93 | unit-category.h \ 94 | unit-manager.c \ 95 | unit-manager.h \ 96 | prelexer.c \ 97 | prelexer.h \ 98 | lexer.c \ 99 | lexer.h \ 100 | parserfunc.c \ 101 | parserfunc.h \ 102 | parser.c \ 103 | parser.h 104 | 105 | mate_calc_cmd_LDADD = \ 106 | $(MATE_CALC_CMD_LIBS) 107 | 108 | test_mp_SOURCES = \ 109 | test-mp.c \ 110 | mp.c \ 111 | mp-binary.c \ 112 | mp-convert.c \ 113 | mp-enums.c \ 114 | mp-enums.h \ 115 | mp-serializer.c \ 116 | mp-serializer.h \ 117 | mp-trigonometric.c 118 | 119 | test_mp_LDADD = \ 120 | $(MATE_CALC_CMD_LIBS) 121 | 122 | test_mp_equation_SOURCES = \ 123 | test-mp-equation.c \ 124 | currency.c \ 125 | currency.h \ 126 | currency-manager.c \ 127 | currency-manager.h \ 128 | mp.c \ 129 | mp-convert.c \ 130 | mp-binary.c \ 131 | mp-enums.c \ 132 | mp-enums.h \ 133 | mp-equation.c \ 134 | mp-serializer.c \ 135 | mp-serializer.h \ 136 | mp-trigonometric.c \ 137 | unit.c \ 138 | unit.h \ 139 | unit-category.c \ 140 | unit-category.h \ 141 | unit-manager.c \ 142 | unit-manager.h \ 143 | prelexer.c \ 144 | prelexer.h \ 145 | lexer.c \ 146 | lexer.h \ 147 | parserfunc.c \ 148 | parserfunc.h \ 149 | parser.c \ 150 | parser.h 151 | 152 | test_mp_equation_LDADD = \ 153 | $(MATE_CALC_CMD_LIBS) 154 | 155 | CLEANFILES = \ 156 | mp-enums.c \ 157 | mp-enums.h \ 158 | $(BUILT_SOURCES) 159 | 160 | # Generate enum types 161 | mp-enums.h: mp-enums.h.template mp-serializer.h 162 | $(AM_V_GEN)$(GLIB_MKENUMS) --template $(srcdir)/mp-enums.h.template $(srcdir)/mp-serializer.h > mp-enums.h 163 | 164 | mp-enums.c: mp-enums.c.template mp-enums.h mp-serializer.h 165 | $(AM_V_GEN)$(GLIB_MKENUMS) --template $(srcdir)/mp-enums.c.template $(srcdir)/mp-serializer.h > mp-enums.c 166 | 167 | # Fix dependencies 168 | math-serializer.c: mp-enums.h 169 | math-equation.c: mp-enums.h 170 | 171 | # Generate resources 172 | mate-calc-resources.h mate-calc-resources.c: org.mate.calculator.gresource.xml Makefile $(shell $(GLIB_COMPILE_RESOURCES) --generate-dependencies --sourcedir $(srcdir) $(srcdir)/org.mate.calculator.gresource.xml) 173 | $(AM_V_GEN) XMLLINT=$(XMLLINT) $(GLIB_COMPILE_RESOURCES) --target $@ --sourcedir $(srcdir) --generate --c-name calculator $< 174 | 175 | 176 | # Install a symlink between mate-calc and mate-calculator 177 | install-exec-hook: 178 | test -e "$(DESTDIR)$(bindir)/mate-calculator" \ 179 | || (cd "$(DESTDIR)$(bindir)" && ln -s mate-calc mate-calculator) 180 | 181 | # Remove the symlink between mate-calc and mate-calculator 182 | uninstall-local: 183 | test -h "$(DESTDIR)$(bindir)/mate-calculator" \ 184 | && rm -f "$(DESTDIR)$(bindir)/mate-calculator" 185 | 186 | EXTRA_DIST = \ 187 | buttons-advanced.ui \ 188 | buttons-basic.ui \ 189 | buttons-financial.ui \ 190 | buttons-programming.ui \ 191 | mate-calc.about \ 192 | mp-enums.c.template \ 193 | mp-enums.h.template \ 194 | org.mate.calculator.gresource.xml \ 195 | history-entry.ui \ 196 | preferences.ui 197 | 198 | DISTCLEANFILES = \ 199 | Makefile.in 200 | 201 | test: mate-calc 202 | ./mate-calc -u 203 | 204 | -include $(top_srcdir)/git.mk 205 | -------------------------------------------------------------------------------- /src/math-variables.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008-2011 Robert Ancell 3 | * 4 | * This program is free software: you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation, either version 2 of the License, or (at your option) any later 7 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 8 | * license. 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | #include "math-variables.h" 15 | #include "mp-serializer.h" 16 | 17 | struct MathVariablesPrivate 18 | { 19 | gchar *file_name; 20 | GHashTable *registers; 21 | MpSerializer *serializer; 22 | }; 23 | 24 | G_DEFINE_TYPE_WITH_PRIVATE (MathVariables, math_variables, G_TYPE_OBJECT); 25 | 26 | MathVariables * 27 | math_variables_new() 28 | { 29 | return g_object_new (math_variables_get_type(), NULL); 30 | } 31 | 32 | static void 33 | registers_load(MathVariables *variables) 34 | { 35 | FILE *f; 36 | char line[1024]; 37 | 38 | f = fopen(variables->priv->file_name, "r"); 39 | if (!f) 40 | return; 41 | 42 | g_hash_table_remove_all(variables->priv->registers); 43 | 44 | while (fgets(line, 1024, f) != NULL) 45 | { 46 | char *name, *value; 47 | MPNumber *t; 48 | 49 | value = strchr(line, '='); 50 | if (!value) 51 | continue; 52 | *value = '\0'; 53 | value = value + 1; 54 | 55 | name = g_strstrip(line); 56 | value = g_strstrip(value); 57 | 58 | t = g_malloc(sizeof(MPNumber)); 59 | *t = mp_new(); 60 | if (mp_set_from_string(value, 10, t) == 0) 61 | g_hash_table_insert(variables->priv->registers, g_strdup(name), t); 62 | else 63 | { 64 | mp_clear(t); 65 | g_free(t); 66 | } 67 | } 68 | fclose(f); 69 | } 70 | 71 | static void 72 | registers_save(MathVariables *variables) 73 | { 74 | gchar *dir; 75 | FILE *f; 76 | GHashTableIter iter; 77 | gpointer key, val; 78 | 79 | dir = g_path_get_dirname(variables->priv->file_name); 80 | g_mkdir_with_parents(dir, 0700); 81 | g_free(dir); 82 | 83 | f = fopen(variables->priv->file_name, "w"); 84 | if (!f) 85 | return; 86 | 87 | g_hash_table_iter_init(&iter, variables->priv->registers); 88 | while (g_hash_table_iter_next(&iter, &key, &val)) 89 | { 90 | gchar *name = key; 91 | MPNumber *value = val; 92 | char *number; 93 | 94 | number = mp_serializer_to_string(variables->priv->serializer, value); 95 | fprintf(f, "%s=%s\n", name, number); 96 | g_free(number); 97 | } 98 | fclose(f); 99 | } 100 | 101 | // FIXME: Sort 102 | gchar ** 103 | math_variables_get_names(MathVariables *variables) 104 | { 105 | GHashTableIter iter; 106 | gpointer key; 107 | gint i = 0; 108 | gchar **names; 109 | 110 | g_return_val_if_fail(variables != NULL, NULL); 111 | 112 | names = g_malloc0(sizeof(gchar *) * (g_hash_table_size(variables->priv->registers) + 1)); 113 | 114 | g_hash_table_iter_init(&iter, variables->priv->registers); 115 | while (g_hash_table_iter_next(&iter, &key, NULL)) 116 | { 117 | gchar *name = key; 118 | names[i] = g_strdup(name); 119 | i++; 120 | } 121 | names[i] = NULL; 122 | 123 | return names; 124 | } 125 | 126 | void 127 | math_variables_set(MathVariables *variables, const char *name, const MPNumber *value) 128 | { 129 | MPNumber *t; 130 | 131 | g_return_if_fail(variables != NULL); 132 | g_return_if_fail(name != NULL); 133 | g_return_if_fail(value != NULL); 134 | 135 | t = g_malloc(sizeof(MPNumber)); 136 | *t = mp_new(); 137 | mp_set_from_mp(value, t); 138 | g_hash_table_insert(variables->priv->registers, g_strdup(name), t); 139 | registers_save(variables); 140 | } 141 | 142 | MPNumber * 143 | math_variables_get(MathVariables *variables, const char *name) 144 | { 145 | g_return_val_if_fail(variables != NULL, NULL); 146 | g_return_val_if_fail(name != NULL, NULL); 147 | return g_hash_table_lookup(variables->priv->registers, name); 148 | } 149 | 150 | void 151 | math_variables_delete(MathVariables *variables, const char *name) 152 | { 153 | g_return_if_fail(variables != NULL); 154 | g_return_if_fail(name != NULL); 155 | g_hash_table_remove(variables->priv->registers, name); 156 | registers_save(variables); 157 | } 158 | 159 | static void 160 | math_variables_class_init (MathVariablesClass *klass) 161 | { 162 | } 163 | 164 | static void 165 | math_variables_init(MathVariables *variables) 166 | { 167 | variables->priv = math_variables_get_instance_private (variables); 168 | variables->priv->registers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); 169 | variables->priv->file_name = g_build_filename(g_get_user_data_dir(), "mate-calc", "registers", NULL); 170 | variables->priv->serializer = mp_serializer_new(MP_DISPLAY_FORMAT_SCIENTIFIC, 10, 50); 171 | mp_serializer_set_radix(variables->priv->serializer, '.'); 172 | registers_load(variables); 173 | } 174 | -------------------------------------------------------------------------------- /.github/workflows/pages.yml: -------------------------------------------------------------------------------- 1 | name: Deploy to GitHub Pages 2 | 3 | on: 4 | push: 5 | branches: [ master, main ] 6 | pull_request: 7 | branches: [ master, main ] 8 | 9 | permissions: 10 | contents: read 11 | pages: write 12 | id-token: write 13 | pull-requests: write 14 | 15 | concurrency: 16 | group: "pages" 17 | cancel-in-progress: false 18 | 19 | jobs: 20 | build-docs: 21 | runs-on: ubuntu-latest 22 | container: 23 | image: 'fedora:latest' 24 | 25 | steps: 26 | - name: Checkout code 27 | uses: actions/checkout@v4 28 | 29 | - name: Install dependencies 30 | run: | 31 | dnf update -y 32 | dnf install -y \ 33 | autoconf-archive \ 34 | clang \ 35 | clang-analyzer \ 36 | cppcheck-htmlreport \ 37 | bison \ 38 | desktop-file-utils \ 39 | flex \ 40 | gcc \ 41 | git \ 42 | gmp-devel \ 43 | gtk3 \ 44 | libmpc-devel \ 45 | libxml2-devel \ 46 | make \ 47 | mate-common \ 48 | mate-desktop-devel \ 49 | mpfr-devel \ 50 | redhat-rpm-config \ 51 | curl \ 52 | which 53 | 54 | - name: Set up environment variables 55 | run: | 56 | export CPU_COUNT=$(nproc) 57 | echo "CPU_COUNT=$CPU_COUNT" >> $GITHUB_ENV 58 | echo "REPO_NAME=mate-calc" >> $GITHUB_ENV 59 | echo "OWNER_NAME=mate-desktop" >> $GITHUB_ENV 60 | export CHECKERS="-enable-checker deadcode.DeadStores -enable-checker alpha.deadcode.UnreachableCode -enable-checker alpha.core.CastSize -enable-checker alpha.core.CastToStruct -enable-checker alpha.core.IdenticalExpr -enable-checker alpha.core.SizeofPtr -enable-checker alpha.security.ArrayBoundV2 -enable-checker alpha.security.MallocOverflow -enable-checker alpha.security.ReturnPtrRange -enable-checker alpha.unix.SimpleStream -enable-checker alpha.unix.cstring.BufferOverlap -enable-checker alpha.unix.cstring.NotNullTerminated -enable-checker alpha.unix.cstring.OutOfBounds -enable-checker alpha.core.FixedAddr -enable-checker security.insecureAPI.strcpy" 61 | echo "CHECKERS=$CHECKERS" >> $GITHUB_ENV 62 | 63 | - name: Generate build system 64 | run: | 65 | NOCONFIGURE=1 ./autogen.sh 66 | 67 | - name: Configure with scan-build 68 | run: | 69 | scan-build $CHECKERS ./configure --enable-compile-warnings=maximum 70 | 71 | - name: Build with scan-build 72 | run: | 73 | scan-build $CHECKERS --keep-cc -o html-report make -j $CPU_COUNT 74 | 75 | - name: Run cppcheck 76 | run: | 77 | cppcheck --xml --output-file=cppcheck.xml --enable=warning,style,performance,portability,information,missingInclude . 78 | cppcheck-htmlreport --title=$REPO_NAME --file=cppcheck.xml --report-dir=cppcheck-htmlreport 79 | 80 | - name: Generate index page 81 | run: | 82 | curl -Ls -o gen-index https://github.com/mate-desktop/mate-dev-scripts/raw/master/travis/gen-index.sh 83 | chmod +x gen-index 84 | ./gen-index -l 20 -i https://github.com/${OWNER_NAME}/mate-icon-theme/raw/master/mate/16x16/apps/accessories-calculator.png 85 | 86 | - name: Setup Pages 87 | if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' 88 | uses: actions/configure-pages@v5 89 | 90 | - name: Upload artifact 91 | if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' 92 | uses: actions/upload-pages-artifact@v3 93 | with: 94 | path: html-report 95 | 96 | - name: Comment on PR with analysis results 97 | if: github.event_name == 'pull_request' 98 | uses: actions/github-script@v7 99 | with: 100 | script: | 101 | const fs = require('fs'); 102 | const path = require('path'); 103 | 104 | // Check if html-report exists and has content 105 | const reportDir = 'html-report'; 106 | let reportCount = 0; 107 | 108 | if (fs.existsSync(reportDir)) { 109 | const files = fs.readdirSync(reportDir); 110 | reportCount = files.filter(f => f.endsWith('.html')).length; 111 | } 112 | 113 | const comment = `## 🔍 Static Analysis Results 114 | 115 | Code analysis completed for this pull request. 116 | 117 | - **Scan-build reports**: ${reportCount} files generated 118 | - **Status**: ${reportCount > 0 ? '⚠️ Issues found' : '✅ No issues found'} 119 | 120 | The detailed reports are available in the workflow artifacts.`; 121 | 122 | github.rest.issues.createComment({ 123 | issue_number: context.issue.number, 124 | owner: context.repo.owner, 125 | repo: context.repo.repo, 126 | body: comment 127 | }); 128 | 129 | deploy: 130 | if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' 131 | environment: 132 | name: github-pages 133 | url: ${{ steps.deployment.outputs.page_url }} 134 | runs-on: ubuntu-latest 135 | needs: build-docs 136 | steps: 137 | - name: Deploy to GitHub Pages 138 | id: deployment 139 | uses: actions/deploy-pages@v4 -------------------------------------------------------------------------------- /.github/workflows/quality.yml: -------------------------------------------------------------------------------- 1 | name: Code Quality 2 | 3 | on: 4 | push: 5 | branches: [ master, main ] 6 | pull_request: 7 | branches: [ master, main ] 8 | 9 | jobs: 10 | lint: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - name: Checkout code 15 | uses: actions/checkout@v4 16 | 17 | - name: Install dependencies 18 | run: | 19 | sudo apt-get update 20 | sudo apt-get install -y \ 21 | clang-format \ 22 | cppcheck \ 23 | shellcheck \ 24 | libxml2-utils \ 25 | desktop-file-utils 26 | 27 | - name: Check C/C++ code formatting 28 | run: | 29 | # Find all C/C++ files and check formatting 30 | echo "::warning::Code formatting check - this is informational only" 31 | find src/ -name "*.c" -o -name "*.h" | while read file; do 32 | echo "Checking format of $file" 33 | if ! clang-format --dry-run "$file" > /dev/null 2>&1; then 34 | echo "::warning file=$file::Code formatting issues found in $file" 35 | fi 36 | done || true 37 | 38 | - name: Run cppcheck 39 | run: | 40 | echo "::warning::Running cppcheck analysis - issues will be reported as warnings" 41 | cppcheck --enable=warning,style,performance,portability,information \ 42 | --suppress=missingIncludeSystem \ 43 | --suppress=unusedFunction \ 44 | --inline-suppr \ 45 | --template='{file}:{line}: {severity}: {message}' \ 46 | src/ 2>&1 | while IFS= read -r line; do 47 | if [[ $line =~ ^(.+):([0-9]+):[[:space:]]*([^:]+):[[:space:]]*(.+)$ ]]; then 48 | file="${BASH_REMATCH[1]}" 49 | lineno="${BASH_REMATCH[2]}" 50 | severity="${BASH_REMATCH[3]}" 51 | message="${BASH_REMATCH[4]}" 52 | echo "::warning file=$file,line=$lineno::$severity: $message" 53 | else 54 | echo "$line" 55 | fi 56 | done || true 57 | 58 | - name: Check shell scripts 59 | run: | 60 | echo "::warning::Running shellcheck analysis - issues will be reported as warnings" 61 | find . -name "*.sh" -type f | while read -r file; do 62 | echo "Checking shell script: $file" 63 | if ! shellcheck "$file"; then 64 | echo "::warning file=$file::Shellcheck found issues in $file" 65 | fi 66 | done || true 67 | 68 | - name: Validate desktop files 69 | run: | 70 | echo "::warning::Validating desktop files - issues will be reported as warnings" 71 | find . -name "*.desktop.in" -type f | while read -r file; do 72 | echo "Validating $file" 73 | # Basic validation - desktop-file-validate would need the processed .desktop file 74 | if ! xmllint --noout --nonet --quiet "$file" 2>/dev/null; then 75 | echo "::warning file=$file::Desktop file validation issues found in $file" 76 | fi 77 | done || true 78 | 79 | - name: Check XML files 80 | run: | 81 | echo "::warning::Validating XML files - issues will be reported as warnings" 82 | find . -name "*.xml" -type f | while read -r file; do 83 | echo "Validating XML: $file" 84 | if ! xmllint --noout "$file" 2>/dev/null; then 85 | echo "::warning file=$file::XML validation issues found in $file" 86 | fi 87 | done || true 88 | 89 | - name: Check for common issues 90 | run: | 91 | echo "::warning::Checking for common code issues - issues will be reported as warnings" 92 | 93 | # Check for trailing whitespace 94 | if grep -r '[[:space:]]$' src/ --exclude-dir=.git; then 95 | echo "::warning::Found trailing whitespace in source files" 96 | fi 97 | 98 | # Check for tabs in source files (if project prefers spaces) 99 | if grep -r $'\t' src/ --include="*.c" --include="*.h" --exclude-dir=.git; then 100 | echo "::warning::Found tabs in source files - consider using spaces for consistency" 101 | fi 102 | 103 | # Always succeed 104 | true 105 | 106 | security: 107 | runs-on: ubuntu-latest 108 | 109 | steps: 110 | - name: Checkout code 111 | uses: actions/checkout@v4 112 | 113 | - name: Run security checks 114 | run: | 115 | echo "::warning::Running security analysis - issues will be reported as warnings" 116 | echo "Checking for potential security issues..." 117 | 118 | # Look for dangerous functions 119 | if grep -r '\(strcpy\|sprintf\|gets\|strcat\)(' src/ --include="*.c"; then 120 | echo "::warning::Found potentially unsafe functions - consider using safer alternatives" 121 | fi 122 | 123 | # Check for TODO/FIXME comments that might indicate security issues 124 | if grep -r 'TODO.*\(security\|vulner\|exploit\)' src/; then 125 | echo "::warning::Found security-related TODO comments" 126 | fi 127 | 128 | if grep -r 'FIXME.*\(security\|vulner\|exploit\)' src/; then 129 | echo "::warning::Found security-related FIXME comments" 130 | fi 131 | 132 | echo "Security check completed" 133 | # Always succeed 134 | true -------------------------------------------------------------------------------- /src/mp-equation-lexer.l: -------------------------------------------------------------------------------- 1 | %option 8bit reentrant bison-locations 2 | %option never-interactive 3 | %option noyywrap noinput nounput 4 | %option prefix="_mp_equation_" 5 | %option extra-type="MPEquationParserState *" 6 | %option outfile="mp-equation-lexer.c" header-file="mp-equation-lexer.h" 7 | 8 | %{ 9 | /* Copyright (c) 2004-2008 Sami Pietila 10 | * Copyright (c) 2008-2009 Robert Ancell 11 | * 12 | * This program is free software; you can redistribute it and/or modify 13 | * it under the terms of the GNU General Public License as published by 14 | * the Free Software Foundation; either version 2, or (at your option) 15 | * any later version. 16 | * 17 | * This program is distributed in the hope that it will be useful, but 18 | * WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | * General Public License for more details. 21 | * 22 | * You should have received a copy of the GNU General Public License 23 | * along with this program; if not, write to the Free Software 24 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 25 | * 02110-1301, USA. 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "mp-equation-private.h" 34 | #include "mp-equation-parser.h" 35 | #include "mp-equation.h" 36 | %} 37 | 38 | 39 | ZERO "0"|"٠"|"۰"|"߀"|"०"|"০"|"੦"|"૦"|"୦"|"௦"|"౦"|"೦"|"൦"|"๐"|"໐"|"༠"|"၀"|"႐"|"០"|"᠐"|"᥆"|"᧐"|"᭐"|"᮰"|"᱀"|"᱐"|"꘠"|"꣐"|"꤀"|"꩐"|"𐒠" 40 | ONE "1"|"١"|"۱"|"߁"|"१"|"১"|"੧"|"૧"|"୧"|"௧"|"౧"|"೧"|"൧"|"๑"|"໑"|"༡"|"၁"|"႑"|"១"|"᠑"|"᥇"|"᧑"|"᭑"|"᮱"|"᱁"|"᱑"|"꘡"|"꣑"|"꤁"|"꩑"|"𐒡" 41 | TWO "2"|"٢"|"۲"|"߂"|"२"|"২"|"੨"|"૨"|"୨"|"௨"|"౨"|"೨"|"൨"|"๒"|"໒"|"༢"|"၂"|"႒"|"២"|"᠒"|"᥈"|"᧒"|"᭒"|"᮲"|"᱂"|"᱒"|"꘢"|"꣒"|"꤂"|"꩒"|"𐒢" 42 | THREE "3"|"٣"|"۳"|"߃"|"३"|"৩"|"੩"|"૩"|"୩"|"௩"|"౩"|"೩"|"൩"|"๓"|"໓"|"༣"|"၃"|"႓"|"៣"|"᠓"|"᥉"|"᧓"|"᭓"|"᮳"|"᱃"|"᱓"|"꘣"|"꣓"|"꤃"|"꩓"|"𐒣" 43 | FOUR "4"|"٤"|"۴"|"߄"|"४"|"৪"|"੪"|"૪"|"୪"|"௪"|"౪"|"೪"|"൪"|"๔"|"໔"|"༤"|"၄"|"႔"|"៤"|"᠔"|"᥊"|"᧔"|"᭔"|"᮴"|"᱄"|"᱔"|"꘤"|"꣔"|"꤄"|"꩔"|"𐒤" 44 | FIVE "5"|"٥"|"۵"|"߅"|"५"|"৫"|"੫"|"૫"|"୫"|"௫"|"౫"|"೫"|"൫"|"๕"|"໕"|"༥"|"၅"|"႕"|"៥"|"᠕"|"᥋"|"᧕"|"᭕"|"᮵"|"᱅"|"᱕"|"꘥"|"꣕"|"꤅"|"꩕"|"𐒥" 45 | SIX "6"|"٦"|"۶"|"߆"|"६"|"৬"|"੬"|"૬"|"୬"|"௬"|"౬"|"೬"|"൬"|"๖"|"໖"|"༦"|"၆"|"႖"|"៦"|"᠖"|"᥌"|"᧖"|"᭖"|"᮶"|"᱆"|"᱖"|"꘦"|"꣖"|"꤆"|"꩖"|"𐒦" 46 | SEVEN "7"|"٧"|"۷"|"߇"|"७"|"৭"|"੭"|"૭"|"୭"|"௭"|"౭"|"೭"|"൭"|"๗"|"໗"|"༧"|"၇"|"႗"|"៧"|"᠗"|"᥍"|"᧗"|"᭗"|"᮷"|"᱇"|"᱗"|"꘧"|"꣗"|"꤇"|"꩗"|"𐒧" 47 | EIGHT "8"|"٨"|"۸"|"߈"|"८"|"৮"|"੮"|"૮"|"୮"|"௮"|"౮"|"೮"|"൮"|"๘"|"໘"|"༨"|"၈"|"႘"|"៨"|"᠘"|"᥎"|"᧘"|"᭘"|"᮸"|"᱈"|"᱘"|"꘨"|"꣘"|"꤈"|"꩘"|"𐒨" 48 | NINE "9"|"٩"|"۹"|"߉"|"९"|"৯"|"੯"|"૯"|"୯"|"௯"|"౯"|"೯"|"൯"|"๙"|"໙"|"༩"|"၉"|"႙"|"៩"|"᠙"|"᥏"|"᧙"|"᭙"|"᮹"|"᱉"|"᱙"|"꘩"|"꣙"|"꤉"|"꩙"|"𐒩" 49 | DECIMAL "."|"," 50 | DEC {ZERO}|{ONE}|{TWO}|{THREE}|{FOUR}|{FIVE}|{SIX}|{SEVEN}|{EIGHT}|{NINE} 51 | HEX {DEC}|[A-F]|[a-f] 52 | SUPER_DIGITS "⁰"|"¹"|"²"|"³"|"⁴"|"⁵"|"⁶"|"⁷"|"⁸"|"⁹" 53 | SUPER_MINUS "⁻" 54 | SUB_DIGITS "₀"|"₁"|"₂"|"₃"|"₄"|"₅"|"₆"|"₇"|"₈"|"₉" 55 | FRACTION "½"|"⅓"|"⅔"|"¼"|"¾"|"⅕"|"⅖"|"⅗"|"⅘"|"⅙"|"⅚"|"⅛"|"⅜"|"⅝"|"⅞" 56 | GREEKS "α"|"β"|"γ"|"δ"|"ε"|"ζ"|"η"|"θ"|"ι"|"κ"|"λ"|"μ"|"ν"|"ξ"|"ο"|"π"|"ρ"|"ς"|"σ"|"τ"|"υ"|"φ"|"χ"|"ψ"|"ω" 57 | DEGREES "°" 58 | MINUTES "'" 59 | SECONDS "\"" 60 | LETTERS [a-zA-Z]|{GREEKS} 61 | 62 | SUP_NUM {SUPER_DIGITS}+ 63 | NSUP_NUM {SUPER_MINUS}{SUPER_DIGITS}+ 64 | SUB_NUM {SUB_DIGITS}+ 65 | WORD {LETTERS}+ 66 | DEC_NUM {DEC}+|{DEC}*{DECIMAL}{DEC}+ 67 | DEF_NUM {HEX}+|{HEX}*{DECIMAL}{HEX}+ 68 | BASE_NUM {HEX}+{SUB_NUM}|{HEX}*{DECIMAL}{HEX}+{SUB_NUM} 69 | ANGLE_NUM {DEC_NUM}{DEGREES}|{DEC}+{DEGREES}{DEC_NUM}{MINUTES}|{DEC}+{DEGREES}{DEC}+{MINUTES}{DEC_NUM}{SECONDS} 70 | 71 | NUMBER {DEF_NUM}|{BASE_NUM}|{FRACTION}|{DEC}+{FRACTION}|{ANGLE_NUM} 72 | VARIABLE {WORD}|{WORD}{SUB_NUM}|{GREEKS} 73 | 74 | MOD [mM][oO][dD] 75 | AND "∧"|[aA][nN][dD] 76 | OR "∨"|[oO][rR] 77 | XOR "⊻"|"⊕"|[xX][oO][rR] 78 | LSHIFT "<<" 79 | RSHIFT ">>" 80 | NOT "¬"|"~"|[nN][oO][tT] 81 | RE "⃰ℜ" 82 | IM "ℑ" 83 | IN [iI][nN] 84 | 85 | %% 86 | 87 | "+" {return tADD;} 88 | "-"|"−" {return tSUBTRACT;} 89 | "*"|"×" {return tMULTIPLY;} 90 | "/"|"∕"|"÷" {return tDIVIDE;} 91 | {MOD} {return tMOD;} 92 | "⌊" {return tLFLOOR;} 93 | "⌋" {return tRFLOOR;} 94 | "⌈" {return tLCEILING;} 95 | "⌉" {return tRCEILING;} 96 | "√" {return tROOT;} 97 | "∛" {return tROOT3;} 98 | "∜" {return tROOT4;} 99 | {LSHIFT} {return tLSHIFT;} 100 | {RSHIFT} {return tRSHIFT;} 101 | {NOT} {return tNOT;} 102 | {AND} {return tAND;} 103 | {OR} {return tOR;} 104 | {XOR} {return tXOR;} 105 | {IN} {return tIN;} 106 | {NUMBER} {if (mp_set_from_string(yytext, _mp_equation_get_extra(yyscanner)->options->base, &yylval->int_t) != 0) REJECT; return tNUMBER;} 107 | {SUP_NUM} {yylval->integer = super_atoi(yytext); return tSUPNUM;} 108 | {NSUP_NUM} {yylval->integer = super_atoi(yytext); return tNSUPNUM;} 109 | {SUB_NUM} {yylval->integer = sub_atoi(yytext); return tSUBNUM;} 110 | {VARIABLE} {\ 111 | MPEquationParserState *state = _mp_equation_get_extra(yyscanner);\ 112 | if (state->function_is_defined(state, yytext)) {\ 113 | yylval->name = strdup(yytext);\ 114 | return tFUNCTION;\ 115 | }\ 116 | else {\ 117 | yylval->name = strdup(yytext);\ 118 | return tVARIABLE;\ 119 | }\ 120 | } 121 | [ \r\t\n] 122 | . {return *yytext;} 123 | 124 | %% 125 | -------------------------------------------------------------------------------- /src/math-equation.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1987-2008 Sun Microsystems, Inc. All Rights Reserved. 3 | * Copyright (C) 2008-2011 Robert Ancell 4 | * 5 | * This program is free software: you can redistribute it and/or modify it under 6 | * the terms of the GNU General Public License as published by the Free Software 7 | * Foundation, either version 2 of the License, or (at your option) any later 8 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 9 | * license. 10 | */ 11 | 12 | #ifndef MATH_EQUATION_H 13 | #define MATH_EQUATION_H 14 | 15 | #include 16 | #include 17 | 18 | #include "mp.h" 19 | #include "math-variables.h" 20 | #include "mp-serializer.h" 21 | 22 | G_BEGIN_DECLS 23 | 24 | #define MATH_TYPE_EQUATION (math_equation_get_type ()) 25 | #define MATH_EQUATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), math_equation_get_type(), MathEquation)) 26 | #define MATH_EQUATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MATH_TYPE_EQUATION, MathEquationClass)) 27 | 28 | typedef struct MathEquationPrivate MathEquationPrivate; 29 | 30 | typedef struct 31 | { 32 | GtkTextBuffer parent_instance; 33 | MathEquationPrivate *priv; 34 | } MathEquation; 35 | 36 | typedef struct 37 | { 38 | GtkTextBufferClass parent_class; 39 | } MathEquationClass; 40 | 41 | typedef enum { 42 | NORMAL, 43 | SUPERSCRIPT, 44 | SUBSCRIPT 45 | } NumberMode; 46 | 47 | GType math_equation_get_type(void); 48 | MathEquation *math_equation_new(void); 49 | 50 | MathVariables *math_equation_get_variables(MathEquation *equation); 51 | 52 | gunichar math_equation_get_digit_text(MathEquation *equation, guint digit); 53 | 54 | void math_equation_set_status(MathEquation *equation, const gchar *status); 55 | const gchar *math_equation_get_status(MathEquation *equation); 56 | 57 | gboolean math_equation_is_empty(MathEquation *equation); 58 | gboolean math_equation_is_result(MathEquation *equation); 59 | gchar *math_equation_get_display(MathEquation *equation); 60 | gchar *math_equation_get_equation(MathEquation *equation); 61 | gboolean math_equation_get_number(MathEquation *equation, MPNumber *z); 62 | 63 | void math_equation_set_number_mode(MathEquation *equation, NumberMode mode); 64 | NumberMode math_equation_get_number_mode(MathEquation *equation); 65 | 66 | void math_equation_set_accuracy(MathEquation *equation, gint accuracy); 67 | gint math_equation_get_accuracy(MathEquation *equation); 68 | 69 | void math_equation_set_show_thousands_separators(MathEquation *equation, gboolean visible); 70 | gboolean math_equation_get_show_thousands_separators(MathEquation *equation); 71 | 72 | void math_equation_set_show_trailing_zeroes(MathEquation *equation, gboolean visible); 73 | gboolean math_equation_get_show_trailing_zeroes(MathEquation *equation); 74 | 75 | void math_equation_set_number_format(MathEquation *equation, MpDisplayFormat format); 76 | MpDisplayFormat math_equation_get_number_format(MathEquation *equation); 77 | 78 | void math_equation_set_base(MathEquation *equation, gint base); 79 | gint math_equation_get_base(MathEquation *equation); 80 | 81 | void math_equation_set_word_size(MathEquation *equation, gint word_size); 82 | gint math_equation_get_word_size(MathEquation *equation); 83 | 84 | void math_equation_set_angle_units(MathEquation *equation, MPAngleUnit angle_unit); 85 | MPAngleUnit math_equation_get_angle_units(MathEquation *equation); 86 | 87 | void math_equation_set_source_currency(MathEquation *equation, const gchar *currency); 88 | const gchar *math_equation_get_source_currency(MathEquation *equation); 89 | 90 | void math_equation_set_target_currency(MathEquation *equation, const gchar *currency); 91 | const gchar *math_equation_get_target_currency(MathEquation *equation); 92 | 93 | void math_equation_set_source_units(MathEquation *equation, const gchar *units); 94 | const gchar *math_equation_get_source_units(MathEquation *equation); 95 | 96 | void math_equation_set_target_units(MathEquation *equation, const gchar *units); 97 | const gchar *math_equation_get_target_units(MathEquation *equation); 98 | 99 | gboolean math_equation_in_solve(MathEquation *equation); 100 | 101 | const MPNumber *math_equation_get_answer(MathEquation *equation); 102 | MpSerializer *math_equation_get_serializer(MathEquation *equation); 103 | 104 | void math_equation_copy(MathEquation *equation); 105 | void math_equation_paste(MathEquation *equation); 106 | void math_equation_undo(MathEquation *equation); 107 | void math_equation_redo(MathEquation *equation); 108 | void math_equation_store(MathEquation *equation, const gchar *name); 109 | void math_equation_recall(MathEquation *equation, const gchar *name); 110 | void math_equation_set(MathEquation *equation, const gchar *text); 111 | void math_equation_set_number(MathEquation *equation, const MPNumber *x); 112 | void math_equation_insert(MathEquation *equation, const gchar *text); 113 | void math_equation_insert_digit(MathEquation *equation, guint digit); 114 | void math_equation_insert_numeric_point(MathEquation *equation); 115 | void math_equation_insert_number(MathEquation *equation, const MPNumber *x); 116 | void math_equation_insert_subtract(MathEquation *equation); 117 | void math_equation_insert_exponent(MathEquation *equation); 118 | void math_equation_solve(MathEquation *equation); 119 | void math_equation_factorize(MathEquation *equation); 120 | void math_equation_delete(MathEquation *equation); 121 | void math_equation_backspace(MathEquation *equation); 122 | void math_equation_clear(MathEquation *equation); 123 | void math_equation_shift(MathEquation *equation, gint count); 124 | void math_equation_toggle_bit(MathEquation *equation, guint bit); 125 | 126 | G_END_DECLS 127 | 128 | #endif /* MATH_EQUATION_H */ 129 | -------------------------------------------------------------------------------- /src/unit.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1987-2008 Sun Microsystems, Inc. All Rights Reserved. 3 | * Copyright (C) 2008-2011 Robert Ancell. 4 | * 5 | * This program is free software: you can redistribute it and/or modify it under 6 | * the terms of the GNU General Public License as published by the Free Software 7 | * Foundation, either version 2 of the License, or (at your option) any later 8 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 9 | * license. 10 | */ 11 | 12 | #include 13 | 14 | #include "unit.h" 15 | #include "mp-serializer.h" 16 | #include "mp-equation.h" 17 | #include "currency-manager.h" // FIXME: Move out of here 18 | 19 | struct UnitPrivate 20 | { 21 | gchar *name; 22 | gchar *display_name; 23 | gchar *format; 24 | GList *symbols; 25 | gchar *from_function; 26 | gchar *to_function; 27 | MpSerializer *serializer; 28 | }; 29 | 30 | G_DEFINE_TYPE_WITH_PRIVATE (Unit, unit, G_TYPE_OBJECT); 31 | 32 | Unit * 33 | unit_new(const gchar *name, 34 | const gchar *display_name, 35 | const gchar *format, 36 | const gchar *from_function, 37 | const gchar *to_function, 38 | const gchar *symbols) 39 | { 40 | Unit *unit = g_object_new(unit_get_type(), NULL); 41 | gchar **symbol_names; 42 | int i; 43 | 44 | unit->priv->name = g_strdup(name); 45 | unit->priv->display_name = g_strdup(display_name); 46 | unit->priv->format = g_strdup(format); 47 | unit->priv->from_function = g_strdup(from_function); 48 | unit->priv->to_function = g_strdup(to_function); 49 | symbol_names = g_strsplit(symbols, ",", 0); 50 | for (i = 0; symbol_names[i]; i++) 51 | unit->priv->symbols = g_list_append(unit->priv->symbols, symbol_names[i]); 52 | g_free(symbol_names); 53 | 54 | return unit; 55 | } 56 | 57 | const gchar * 58 | unit_get_name(Unit *unit) 59 | { 60 | g_return_val_if_fail (unit != NULL, NULL); 61 | return unit->priv->name; 62 | } 63 | 64 | const gchar * 65 | unit_get_display_name(Unit *unit) 66 | { 67 | g_return_val_if_fail (unit != NULL, NULL); 68 | return unit->priv->display_name; 69 | } 70 | 71 | gboolean 72 | unit_matches_symbol(Unit *unit, const gchar *symbol) 73 | { 74 | GList *iter; 75 | 76 | g_return_val_if_fail (unit != NULL, FALSE); 77 | g_return_val_if_fail (symbol != NULL, FALSE); 78 | 79 | for (iter = unit->priv->symbols; iter; iter = iter->next) { 80 | gchar *s = iter->data; 81 | if (strcmp(s, symbol) == 0) 82 | return TRUE; 83 | } 84 | 85 | return FALSE; 86 | } 87 | 88 | const GList * 89 | unit_get_symbols(Unit *unit) 90 | { 91 | g_return_val_if_fail (unit != NULL, NULL); 92 | return unit->priv->symbols; 93 | } 94 | 95 | static int 96 | variable_is_defined(const char *name, void *data) 97 | { 98 | return TRUE; 99 | } 100 | 101 | static int 102 | get_variable(const char *name, MPNumber *z, void *data) 103 | { 104 | MPNumber *x = data; 105 | mp_set_from_mp(x, z); 106 | return TRUE; 107 | } 108 | 109 | static gboolean 110 | solve_function(const gchar *function, const MPNumber *x, MPNumber *z) 111 | { 112 | MPEquationOptions options; 113 | int ret; 114 | 115 | memset(&options, 0, sizeof(options)); 116 | options.base = 10; 117 | options.wordlen = 32; 118 | options.variable_is_defined = variable_is_defined; 119 | options.get_variable = get_variable; 120 | options.callback_data = (void *)x; 121 | ret = mp_equation_parse(function, &options, z, NULL); 122 | if (ret) { 123 | g_warning("Failed to convert value: %s", function); 124 | return FALSE; 125 | } 126 | 127 | return TRUE; 128 | } 129 | 130 | gboolean 131 | unit_convert_from(Unit *unit, const MPNumber *x, MPNumber *z) 132 | { 133 | g_return_val_if_fail(unit != NULL, FALSE); 134 | g_return_val_if_fail(x != NULL, FALSE); 135 | g_return_val_if_fail(z != NULL, FALSE); 136 | 137 | if (unit->priv->from_function) 138 | return solve_function(unit->priv->from_function, x, z); 139 | else { 140 | // FIXME: Hack to make currency work 141 | const MPNumber *r; 142 | r = currency_manager_get_value(currency_manager_get_default(), unit->priv->name); 143 | if (!r) 144 | return FALSE; 145 | mp_divide(x, r, z); 146 | 147 | return TRUE; 148 | } 149 | } 150 | 151 | gboolean 152 | unit_convert_to(Unit *unit, const MPNumber *x, MPNumber *z) 153 | { 154 | g_return_val_if_fail(unit != NULL, FALSE); 155 | g_return_val_if_fail(x != NULL, FALSE); 156 | g_return_val_if_fail(x != NULL, FALSE); 157 | 158 | if (unit->priv->from_function) 159 | return solve_function(unit->priv->to_function, x, z); 160 | else { 161 | // FIXME: Hack to make currency work 162 | const MPNumber *r; 163 | r = currency_manager_get_value(currency_manager_get_default(), unit->priv->name); 164 | if (!r) 165 | return FALSE; 166 | mp_multiply(x, r, z); 167 | 168 | return TRUE; 169 | } 170 | } 171 | 172 | gchar * 173 | unit_format(Unit *unit, MPNumber *x) 174 | { 175 | gchar *number_text, *text; 176 | 177 | g_return_val_if_fail(unit != NULL, FALSE); 178 | g_return_val_if_fail(x != NULL, FALSE); 179 | 180 | number_text = mp_serializer_to_string(unit->priv->serializer, x); 181 | text = g_strdup_printf(unit->priv->format, number_text); 182 | g_free(number_text); 183 | 184 | return text; 185 | } 186 | 187 | static void 188 | unit_class_init(UnitClass *klass) 189 | { 190 | } 191 | 192 | static void 193 | unit_init(Unit *unit) 194 | { 195 | unit->priv = unit_get_instance_private (unit); 196 | unit->priv->serializer = mp_serializer_new(MP_DISPLAY_FORMAT_AUTOMATIC, 10, 2); 197 | mp_serializer_set_leading_digits(unit->priv->serializer, 6); 198 | } 199 | -------------------------------------------------------------------------------- /src/math-history.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020-2021 MATE developers 3 | * 4 | * This program is free software: you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation, either version 2 of the License, or (at your option) any later 7 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 8 | * license. 9 | * 10 | * 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include "math-history.h" 18 | 19 | struct MathHistoryPrivate 20 | { 21 | MathEquation *equation; 22 | 23 | MpSerializer *serializer; 24 | gchar *last_equation; 25 | int current; /* 0 is the first entry, rows-1 the most recent entry */ 26 | int rows; 27 | GtkWidget *listbox; 28 | }; 29 | 30 | G_DEFINE_TYPE_WITH_PRIVATE(MathHistory, math_history, GTK_TYPE_SCROLLED_WINDOW); 31 | 32 | MathHistory * 33 | math_history_new(MathEquation *equation) 34 | { 35 | MathHistory *history = g_object_new(math_history_get_type(), NULL); 36 | history->priv->equation = g_object_ref(equation); 37 | return history; 38 | } 39 | 40 | static void 41 | scroll_bottom_cb(MathHistory *history, gpointer data) 42 | { 43 | GtkAdjustment *adjustment; 44 | // TODO make this dynamic, do not hardcode listbox_height_request/number_of_rows 45 | int width, height; 46 | 47 | adjustment = gtk_list_box_get_adjustment(GTK_LIST_BOX(history->priv->listbox)); 48 | gtk_widget_get_size_request(GTK_WIDGET(history), &width, &height); 49 | gtk_adjustment_set_page_size(adjustment, height / 3); 50 | gtk_adjustment_set_value (adjustment, gtk_adjustment_get_upper (adjustment) 51 | - gtk_adjustment_get_page_size (adjustment)); 52 | } 53 | 54 | void 55 | math_history_insert_entry (MathHistory *history, char *equation, MPNumber *answer) 56 | { 57 | if (g_strcmp0(history->priv->last_equation, equation) == 0 && history->priv->rows >= 1) 58 | { 59 | return; 60 | } 61 | 62 | MathHistoryEntry *entry = math_history_entry_new(history->priv->equation); 63 | 64 | math_history_entry_insert_entry(entry, equation, answer, history->priv->serializer); 65 | 66 | gtk_list_box_insert(GTK_LIST_BOX(history->priv->listbox), GTK_WIDGET(entry), -1); 67 | gtk_widget_set_can_focus(GTK_WIDGET(entry), FALSE); 68 | gtk_widget_show(GTK_WIDGET(entry)); 69 | 70 | g_free(history->priv->last_equation); 71 | 72 | history->priv->last_equation = g_strdup(equation); 73 | history->priv->rows++; 74 | history->priv->current = history->priv->rows; 75 | g_signal_emit_by_name(history, "row-added"); 76 | } 77 | 78 | void 79 | math_history_clear(MathHistory *history) 80 | { 81 | GList *children, *iter; 82 | 83 | history->priv->rows = 0; 84 | history->priv->current = 0; 85 | children = gtk_container_get_children(GTK_CONTAINER(history->priv->listbox)); 86 | for (iter = children; iter != NULL; iter = g_list_next(iter)) 87 | gtk_widget_destroy(GTK_WIDGET(iter->data)); 88 | g_list_free(children); 89 | } 90 | 91 | gpointer 92 | math_history_get_entry_at(MathHistory *history, int index) 93 | { 94 | if (index >= 0 && index < history->priv->rows) 95 | return MATH_HISTORY_ENTRY(gtk_list_box_get_row_at_index(GTK_LIST_BOX(history->priv->listbox), index)); 96 | return NULL; 97 | } 98 | 99 | void 100 | math_history_set_current(MathHistory *history, int value) 101 | { 102 | history->priv->current = CLAMP (history->priv->current + value, 0, history->priv->rows - 1); 103 | } 104 | 105 | int 106 | math_history_get_current(MathHistory *history) 107 | { 108 | return history->priv->current; 109 | } 110 | 111 | void 112 | math_history_set_serializer(MathHistory *history, MpSerializer *serializer) 113 | { 114 | history->priv->serializer = serializer; 115 | 116 | GList *children, *iter; 117 | children = gtk_container_get_children(GTK_CONTAINER(history->priv->listbox)); 118 | for (iter = children; iter != NULL; iter = g_list_next(iter)) 119 | math_history_entry_redisplay(MATH_HISTORY_ENTRY(iter->data), serializer); 120 | g_list_free(children); 121 | } 122 | 123 | static void 124 | math_history_class_init(MathHistoryClass *klass) 125 | { 126 | g_signal_new("row-added", 127 | G_TYPE_FROM_CLASS(klass), 128 | G_SIGNAL_RUN_FIRST, 129 | 0, 130 | NULL, 131 | NULL, 132 | NULL, 133 | G_TYPE_NONE, 134 | 0, 135 | NULL); 136 | } 137 | 138 | static void 139 | math_history_init(MathHistory *history) 140 | { 141 | history->priv = math_history_get_instance_private(history); 142 | 143 | gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(history), GTK_SHADOW_IN); 144 | gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(history), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); 145 | gtk_scrolled_window_set_placement(GTK_SCROLLED_WINDOW(history), GTK_CORNER_TOP_LEFT); 146 | 147 | history->priv->serializer = NULL; 148 | history->priv->current = 0; 149 | history->priv->rows = 0; 150 | history->priv->last_equation = g_strdup(""); 151 | history->priv->listbox = gtk_list_box_new(); 152 | 153 | gtk_list_box_set_selection_mode(GTK_LIST_BOX(history->priv->listbox), GTK_SELECTION_NONE); 154 | gtk_widget_show(GTK_WIDGET(history->priv->listbox)); 155 | 156 | gtk_container_add(GTK_CONTAINER(history), history->priv->listbox); 157 | gtk_widget_set_valign(GTK_WIDGET(history->priv->listbox), GTK_ALIGN_END); 158 | gtk_widget_set_size_request(GTK_WIDGET(history), 100, 100); 159 | gtk_widget_set_can_focus(GTK_WIDGET(history), FALSE); 160 | 161 | g_signal_connect(history, "row-added", G_CALLBACK(scroll_bottom_cb), NULL); 162 | } 163 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build and Test 2 | 3 | on: 4 | push: 5 | branches: [ master, main ] 6 | tags: [ 'v*' ] 7 | pull_request: 8 | branches: [ master, main ] 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | strategy: 14 | matrix: 15 | distro: 16 | - 'debian:testing' 17 | - 'fedora:latest' 18 | include: 19 | - distro: 'debian:testing' 20 | distro_name: 'debian' 21 | - distro: 'fedora:latest' 22 | distro_name: 'fedora' 23 | 24 | container: 25 | image: ${{ matrix.distro }} 26 | 27 | steps: 28 | - name: Checkout code 29 | uses: actions/checkout@v4 30 | 31 | - name: Install dependencies (Debian) 32 | if: matrix.distro_name == 'debian' 33 | run: | 34 | apt-get update 35 | apt-get install -y \ 36 | autopoint \ 37 | clang \ 38 | clang-tools \ 39 | cppcheck \ 40 | gcc \ 41 | git \ 42 | libatk1.0-dev \ 43 | libglib2.0-dev \ 44 | libgmp-dev \ 45 | libgtk-3-dev \ 46 | libmpc-dev \ 47 | libmpfr-dev \ 48 | libxml2-dev \ 49 | make \ 50 | mate-common \ 51 | yelp-tools \ 52 | bison \ 53 | flex \ 54 | curl 55 | 56 | - name: Install dependencies (Fedora) 57 | if: matrix.distro_name == 'fedora' 58 | run: | 59 | dnf update -y 60 | dnf install -y \ 61 | autoconf-archive \ 62 | clang \ 63 | clang-analyzer \ 64 | cppcheck-htmlreport \ 65 | bison \ 66 | desktop-file-utils \ 67 | flex \ 68 | gcc \ 69 | git \ 70 | gmp-devel \ 71 | gtk3 \ 72 | libmpc-devel \ 73 | libxml2-devel \ 74 | make \ 75 | mate-common \ 76 | mate-desktop-devel \ 77 | mpfr-devel \ 78 | redhat-rpm-config \ 79 | curl \ 80 | which 81 | 82 | - name: Set up environment variables 83 | run: | 84 | export CPU_COUNT=$(nproc) 85 | echo "CPU_COUNT=$CPU_COUNT" >> $GITHUB_ENV 86 | echo "DISTRO_NAME=${{ matrix.distro_name }}" >> $GITHUB_ENV 87 | echo "REPO_NAME=mate-calc" >> $GITHUB_ENV 88 | echo "OWNER_NAME=mate-desktop" >> $GITHUB_ENV 89 | export CHECKERS="-enable-checker deadcode.DeadStores -enable-checker alpha.deadcode.UnreachableCode -enable-checker alpha.core.CastSize -enable-checker alpha.core.CastToStruct -enable-checker alpha.core.IdenticalExpr -enable-checker alpha.core.SizeofPtr -enable-checker alpha.security.ArrayBoundV2 -enable-checker alpha.security.MallocOverflow -enable-checker alpha.security.ReturnPtrRange -enable-checker alpha.unix.SimpleStream -enable-checker alpha.unix.cstring.BufferOverlap -enable-checker alpha.unix.cstring.NotNullTerminated -enable-checker alpha.unix.cstring.OutOfBounds -enable-checker alpha.core.FixedAddr -enable-checker security.insecureAPI.strcpy" 90 | echo "CHECKERS=$CHECKERS" >> $GITHUB_ENV 91 | 92 | - name: Run cppcheck (Debian only) 93 | if: matrix.distro_name == 'debian' 94 | shell: bash 95 | run: | 96 | export CFLAGS="${CFLAGS:-} -Wsign-compare" 97 | cppcheck --enable=warning,style,performance,portability,information,missingInclude . 98 | 99 | - name: Generate build system 100 | run: | 101 | NOCONFIGURE=1 ./autogen.sh 102 | 103 | - name: Configure with scan-build 104 | run: | 105 | scan-build $CHECKERS ./configure --enable-compile-warnings=maximum 106 | 107 | - name: Build with scan-build 108 | shell: bash 109 | run: | 110 | if [ $CPU_COUNT -gt 1 ]; then 111 | if [ "$DISTRO_NAME" == "debian" ]; then 112 | scan-build $CHECKERS --keep-cc --use-cc=clang --use-c++=clang++ -o html-report make -j $CPU_COUNT 113 | make clean 114 | fi 115 | scan-build $CHECKERS --keep-cc -o html-report make -j $CPU_COUNT 116 | else 117 | if [ "$DISTRO_NAME" == "debian" ]; then 118 | scan-build $CHECKERS --keep-cc --use-cc=clang --use-c++=clang++ -o html-report make 119 | make clean 120 | fi 121 | scan-build $CHECKERS --keep-cc -o html-report make 122 | fi 123 | 124 | - name: Run additional checks (Fedora only) 125 | if: matrix.distro_name == 'fedora' 126 | run: | 127 | cppcheck --xml --output-file=cppcheck.xml --enable=warning,style,performance,portability,information,missingInclude . 128 | cppcheck-htmlreport --title=$REPO_NAME --file=cppcheck.xml --report-dir=cppcheck-htmlreport 129 | 130 | - name: Generate index (Fedora only) 131 | if: matrix.distro_name == 'fedora' 132 | run: | 133 | curl -Ls -o gen-index https://github.com/mate-desktop/mate-dev-scripts/raw/master/travis/gen-index.sh 134 | chmod +x gen-index 135 | ./gen-index -l 20 -i https://github.com/${OWNER_NAME}/mate-icon-theme/raw/master/mate/16x16/apps/accessories-calculator.png 136 | 137 | - name: Run distcheck 138 | run: | 139 | make distcheck 140 | 141 | - name: Upload HTML reports (Fedora only) 142 | if: matrix.distro_name == 'fedora' 143 | uses: actions/upload-artifact@v4 144 | with: 145 | name: html-report-${{ matrix.distro_name }} 146 | path: html-report/ 147 | retention-days: 30 148 | 149 | - name: Upload cppcheck reports (Fedora only) 150 | if: matrix.distro_name == 'fedora' 151 | uses: actions/upload-artifact@v4 152 | with: 153 | name: cppcheck-report-${{ matrix.distro_name }} 154 | path: cppcheck-htmlreport/ 155 | retention-days: 30 156 | 157 | - name: Upload distribution archives 158 | if: matrix.distro_name == 'fedora' 159 | uses: actions/upload-artifact@v4 160 | with: 161 | name: distribution-archives 162 | path: mate-calc-*.tar.xz 163 | retention-days: 90 -------------------------------------------------------------------------------- /src/mp-binary.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1987-2008 Sun Microsystems, Inc. All Rights Reserved. 3 | * Copyright (C) 2008-2011 Robert Ancell 4 | * 5 | * This program is free software: you can redistribute it and/or modify it under 6 | * the terms of the GNU General Public License as published by the Free Software 7 | * Foundation, either version 2 of the License, or (at your option) any later 8 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 9 | * license. 10 | */ 11 | 12 | #include 13 | 14 | #include "mp.h" 15 | #include "mp-serializer.h" 16 | 17 | // FIXME: Make dynamic 18 | #define MAX_DIGITS 1000 19 | 20 | static char digits[] = "0123456789ABCDEF"; 21 | 22 | static int hex_to_int(char digit) 23 | { 24 | if (digit >= '0' && digit <= '9') 25 | return digit - '0'; 26 | if (digit >= 'A' && digit <= 'F') 27 | return digit - 'A' + 10; 28 | if (digit >= 'a' && digit <= 'f') 29 | return digit - 'a' + 10; 30 | return 0; 31 | } 32 | 33 | static gchar * 34 | to_hex_string(const MPNumber *x) 35 | { 36 | MpSerializer *serializer; 37 | gchar *result; 38 | 39 | serializer = mp_serializer_new(MP_DISPLAY_FORMAT_FIXED, 16, 0); 40 | result = mp_serializer_to_string(serializer, x); 41 | g_object_unref(serializer); 42 | 43 | return result; 44 | } 45 | 46 | static void 47 | mp_bitwise(const MPNumber *x, const MPNumber *y, int (*bitwise_operator)(int, int), MPNumber *z, int wordlen) 48 | { 49 | char *text1, *text2, text_out[MAX_DIGITS], text_out2[MAX_DIGITS]; 50 | int offset1, offset2, offset_out; 51 | 52 | text1 = to_hex_string(x); 53 | text2 = to_hex_string(y); 54 | offset1 = strlen(text1) - 1; 55 | offset2 = strlen(text2) - 1; 56 | offset_out = wordlen / 4 - 1; 57 | if (offset_out <= 0) { 58 | offset_out = offset1 > offset2 ? offset1 : offset2; 59 | } 60 | if (offset_out > 0 && (offset_out < offset1 || offset_out < offset2)) { 61 | g_free(text1); 62 | g_free(text2); 63 | mp_set_from_integer(0, z); 64 | mperr("Overflow. Try a bigger word size"); 65 | return; 66 | } 67 | 68 | /* Perform bitwise operator on each character from right to left */ 69 | for (text_out[offset_out+1] = '\0'; offset_out >= 0; offset_out--) { 70 | int v1 = 0, v2 = 0; 71 | 72 | if (offset1 >= 0) { 73 | v1 = hex_to_int(text1[offset1]); 74 | offset1--; 75 | } 76 | if (offset2 >= 0) { 77 | v2 = hex_to_int(text2[offset2]); 78 | offset2--; 79 | } 80 | text_out[offset_out] = digits[bitwise_operator(v1, v2)]; 81 | } 82 | 83 | snprintf(text_out2, MAX_DIGITS, "%s", text_out); 84 | mp_set_from_string(text_out2, 16, z); 85 | g_free(text1); 86 | g_free(text2); 87 | } 88 | 89 | static int mp_bitwise_and(int v1, int v2) { return v1 & v2; } 90 | static int mp_bitwise_or(int v1, int v2) { return v1 | v2; } 91 | static int mp_bitwise_xor(int v1, int v2) { return v1 ^ v2; } 92 | static int mp_bitwise_not(int v1, int dummy) { return v1 ^ 0xF; } 93 | 94 | bool 95 | mp_is_overflow (const MPNumber *x, int wordlen) 96 | { 97 | bool is_overflow; 98 | MPNumber tmp1 = mp_new(); 99 | MPNumber tmp2 = mp_new(); 100 | mp_set_from_integer(2, &tmp1); 101 | mp_xpowy_integer(&tmp1, wordlen, &tmp2); 102 | is_overflow = mp_is_greater_than (&tmp2, x); 103 | mp_clear(&tmp1); 104 | mp_clear(&tmp2); 105 | return is_overflow; 106 | } 107 | 108 | void 109 | mp_and(const MPNumber *x, const MPNumber *y, MPNumber *z) 110 | { 111 | if (!mp_is_positive_integer(x) || !mp_is_positive_integer(y)) 112 | { 113 | /* Translators: Error displayed when boolean AND attempted on non-integer values */ 114 | mperr(_("Boolean AND is only defined for positive integers")); 115 | } 116 | 117 | mp_bitwise(x, y, mp_bitwise_and, z, 0); 118 | } 119 | 120 | void 121 | mp_or(const MPNumber *x, const MPNumber *y, MPNumber *z) 122 | { 123 | if (!mp_is_positive_integer(x) || !mp_is_positive_integer(y)) 124 | { 125 | /* Translators: Error displayed when boolean OR attempted on non-integer values */ 126 | mperr(_("Boolean OR is only defined for positive integers")); 127 | } 128 | 129 | mp_bitwise(x, y, mp_bitwise_or, z, 0); 130 | } 131 | 132 | void 133 | mp_xor(const MPNumber *x, const MPNumber *y, MPNumber *z) 134 | { 135 | if (!mp_is_positive_integer(x) || !mp_is_positive_integer(y)) 136 | { 137 | /* Translators: Error displayed when boolean XOR attempted on non-integer values */ 138 | mperr(_("Boolean XOR is only defined for positive integers")); 139 | } 140 | 141 | mp_bitwise(x, y, mp_bitwise_xor, z, 0); 142 | } 143 | 144 | void 145 | mp_not(const MPNumber *x, int wordlen, MPNumber *z) 146 | { 147 | MPNumber temp = mp_new(); 148 | 149 | mp_set_from_integer(0, &temp); 150 | 151 | if (!mp_is_positive_integer(x)) 152 | { 153 | /* Translators: Error displayed when boolean NOT attempted on non-integer values */ 154 | mperr(_("Boolean NOT is only defined for positive integers")); 155 | } 156 | 157 | mp_bitwise(x, &temp, mp_bitwise_not, z, wordlen); 158 | mp_clear(&temp); 159 | } 160 | 161 | void 162 | mp_shift(const MPNumber *x, int count, MPNumber *z) 163 | { 164 | if (!mp_is_integer(x)) { 165 | /* Translators: Error displayed when bit shift attempted on non-integer values */ 166 | mperr(_("Shift is only possible on integer values")); 167 | return; 168 | } 169 | 170 | MPNumber multiplier = mp_new(); 171 | mp_set_from_integer(1, &multiplier); 172 | if (count >= 0) { 173 | for (int i = 0; i < count; i++) 174 | mp_multiply_integer(&multiplier, 2, &multiplier); 175 | mp_multiply(x, &multiplier, z); 176 | } 177 | else { 178 | for (int i = 0; i < -count; i++) 179 | mp_multiply_integer(&multiplier, 2, &multiplier); 180 | mp_divide(x, &multiplier, z); 181 | mp_floor(z, z); 182 | } 183 | mp_clear(&multiplier); 184 | } 185 | 186 | void 187 | mp_ones_complement(const MPNumber *x, int wordlen, MPNumber *z) 188 | { 189 | MPNumber t = mp_new(); 190 | mp_set_from_integer(0, &t); 191 | mp_bitwise(x, &t, mp_bitwise_xor, z, wordlen); 192 | mp_not(z, wordlen, z); 193 | mp_clear(&t); 194 | } 195 | 196 | void 197 | mp_twos_complement(const MPNumber *x, int wordlen, MPNumber *z) 198 | { 199 | mp_ones_complement (x, wordlen, z); 200 | mp_add_integer (z, 1, z); 201 | } 202 | -------------------------------------------------------------------------------- /src/prelexer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "prelexer.h" 7 | 8 | /* Creates a scanner state which will be useful for accessing the lexer later. */ 9 | PreLexerState* 10 | pl_create_scanner(const gchar* input) 11 | { 12 | PreLexerState* state; 13 | assert(input != NULL); 14 | assert(g_utf8_validate(input, -1, NULL)); 15 | state = (PreLexerState *) malloc(sizeof(PreLexerState)); 16 | assert(state != NULL); 17 | state->stream = g_strdup(input); 18 | state->length = strlen(state->stream); /* Can't find a GLib replacement of strlen. The mailing list discussion says, it is not implemented because strlen is perfectly capable. :) */ 19 | state->next_index = 0; 20 | state->mark_index = 0; 21 | return state; 22 | } 23 | 24 | /* Destroy and free memory used by LexerState object. */ 25 | void 26 | pl_destroy_scanner(PreLexerState* state) 27 | { 28 | free(state->stream); 29 | free(state); 30 | } 31 | 32 | /* Roll back last scanned unichar. */ 33 | void 34 | pl_roll_back(PreLexerState* state) 35 | { 36 | gchar* tmp; 37 | tmp = g_utf8_find_prev_char(state->stream, state->stream + state->next_index); 38 | if(tmp == NULL) 39 | /* Already at the beginning of the stram. Reset index. */ 40 | state->next_index = 0; 41 | else 42 | state->next_index = tmp - state->stream; 43 | } 44 | 45 | /* Get validated gunichar from input stream. */ 46 | gunichar 47 | pl_get_next_gunichar(PreLexerState* state) 48 | { 49 | gunichar ret; 50 | if(state->next_index >= state->length) 51 | { 52 | /* To prevent scanning last letter multiple times, when a single unconditional rollback is used. */ 53 | if(state->next_index == state->length) 54 | state->next_index++; 55 | return 0; 56 | } 57 | ret = g_utf8_get_char_validated(state->stream + state->next_index, -1); 58 | state->next_index = g_utf8_next_char(state->stream + state->next_index) - state->stream; 59 | return ret; 60 | } 61 | 62 | /* Set marker index. To be used for highlighting and error reporting. */ 63 | void 64 | pl_set_marker(PreLexerState* state) 65 | { 66 | state->mark_index = state->next_index; 67 | } 68 | 69 | /* Get marked substring. To be used for error reporting. */ 70 | gchar* 71 | pl_get_marked_substring(const PreLexerState* state) 72 | { 73 | return g_strndup(state->stream + state->mark_index, state->next_index - state->mark_index); 74 | } 75 | 76 | /* Compares a list of strings with given unichar. To be used by pl_get_next_token() only. */ 77 | static gboolean 78 | pl_compare_all(const gunichar ch, const gint count, gchar *arr[]) 79 | { 80 | gint l; 81 | for(l = 0; l < count; l++) 82 | { 83 | if(ch == g_utf8_get_char_validated(arr[l], -1)) 84 | return TRUE; 85 | } 86 | return FALSE; 87 | } 88 | 89 | /* Pre-Lexer tokanizer. To be called only by Lexer. */ 90 | LexerTokenType 91 | pl_get_next_token(PreLexerState* state) 92 | { 93 | gunichar ch = pl_get_next_gunichar(state); 94 | if(pl_compare_all(ch, 2, (gchar*[]){",","."})) 95 | return PL_DECIMAL; 96 | 97 | if(g_unichar_isdigit(ch) || pl_compare_all(ch, 10, (gchar*[]){"〇","〡","〢","〣","〤","〥","〦","〧","〨","〩"})) 98 | return PL_DIGIT; /* 0-9 */ 99 | 100 | if(g_unichar_isxdigit(ch)) 101 | return PL_HEX; /* This is supposed to report just the A-F. */ 102 | 103 | if(pl_compare_all(ch, 10, (gchar*[]){"⁰","¹","²","³","⁴","⁵","⁶","⁷","⁸","⁹"})) 104 | return PL_SUPER_DIGIT; 105 | 106 | if(pl_compare_all(ch, 1, (gchar*[]){"⁻"})) 107 | return PL_SUPER_MINUS; 108 | 109 | if(pl_compare_all(ch, 10, (gchar*[]){"₀","₁","₂","₃","₄","₅","₆","₇","₈","₉"})) 110 | return PL_SUB_DIGIT; 111 | 112 | if(pl_compare_all(ch, 15, (gchar*[]){"½","⅓","⅔","¼","¾","⅕","⅖","⅗","⅘","⅙","⅚","⅛","⅜","⅝","⅞"})) 113 | return PL_FRACTION; 114 | 115 | if(pl_compare_all(ch, 1, (gchar*[]){"°"})) 116 | return PL_DEGREE; 117 | 118 | if(pl_compare_all(ch, 1, (gchar*[]){"'"})) 119 | return PL_MINUTE; 120 | 121 | if(pl_compare_all(ch, 1, (gchar*[]){"\""})) 122 | return PL_SECOND; 123 | 124 | if(g_unichar_isalpha(ch)) 125 | return PL_LETTER; /* All alphabets excluding A-F. [a-fA-F] are reported as PL_HEX. */ 126 | 127 | if(pl_compare_all(ch, 1, (gchar*[]){"∧"})) 128 | return T_AND; 129 | 130 | if(pl_compare_all(ch, 1, (gchar*[]){"∨"})) 131 | return T_OR; 132 | 133 | if(pl_compare_all(ch, 2, (gchar*[]){"⊻","⊕"})) 134 | return T_XOR; 135 | 136 | if(pl_compare_all(ch, 2, (gchar*[]){"¬","~"})) 137 | return T_NOT; 138 | 139 | if(pl_compare_all(ch, 1, (gchar*[]){"+"})) 140 | return T_ADD; 141 | 142 | if(pl_compare_all(ch, 3, (gchar*[]){"-","−","–"})) 143 | return T_SUBTRACT; 144 | 145 | if(pl_compare_all(ch, 2, (gchar*[]){"*","×"})) 146 | return T_MULTIPLY; 147 | 148 | if(pl_compare_all(ch, 3, (gchar*[]){"/","∕","÷"})) 149 | return T_DIV; 150 | 151 | if(pl_compare_all(ch, 1, (gchar*[]){"⌊"})) 152 | return T_L_FLOOR; 153 | 154 | if(pl_compare_all(ch, 1, (gchar*[]){"⌋"})) 155 | return T_R_FLOOR; 156 | 157 | if(pl_compare_all(ch, 1, (gchar*[]){"⌈"})) 158 | return T_L_CEILING; 159 | 160 | if(pl_compare_all(ch, 1, (gchar*[]){"⌉"})) 161 | return T_R_CEILING; 162 | 163 | if(pl_compare_all(ch, 1, (gchar*[]){"√"})) 164 | return T_ROOT; 165 | 166 | if(pl_compare_all(ch, 1, (gchar*[]){"∛"})) 167 | return T_ROOT_3; 168 | 169 | if(pl_compare_all(ch, 1, (gchar*[]){"∜"})) 170 | return T_ROOT_4; 171 | 172 | if(pl_compare_all(ch, 1, (gchar*[]){"="})) 173 | return T_ASSIGN; 174 | 175 | if(pl_compare_all(ch, 1, (gchar*[]){"("})) 176 | return T_L_R_BRACKET; 177 | 178 | if(pl_compare_all(ch, 1, (gchar*[]){")"})) 179 | return T_R_R_BRACKET; 180 | 181 | if(pl_compare_all(ch, 1, (gchar*[]){"["})) 182 | return T_L_S_BRACKET; 183 | 184 | if(pl_compare_all(ch, 1, (gchar*[]){"]"})) 185 | return T_R_S_BRACKET; 186 | 187 | if(pl_compare_all(ch, 1, (gchar*[]){"{"})) 188 | return T_L_C_BRACKET; 189 | 190 | if(pl_compare_all(ch, 1, (gchar*[]){"}"})) 191 | return T_R_C_BRACKET; 192 | 193 | if(pl_compare_all(ch, 1, (gchar*[]){"|"})) 194 | return T_ABS; 195 | 196 | if(pl_compare_all(ch, 1, (gchar*[]){"^"})) 197 | return T_POWER; 198 | 199 | if(pl_compare_all(ch, 1, (gchar*[]){"!"})) 200 | return T_FACTORIAL; 201 | 202 | if(pl_compare_all(ch, 1, (gchar*[]){"%"})) 203 | return T_PERCENTAGE; 204 | 205 | if(pl_compare_all(ch, 4, (gchar*[]){" ","\r","\t","\n"})) 206 | /* Gotta ignore'Em all!!! ;) */ 207 | return PL_SKIP; 208 | 209 | if(ch == 0) 210 | return PL_EOS; 211 | 212 | /* There is no spoon. */ 213 | return T_UNKNOWN; 214 | } 215 | -------------------------------------------------------------------------------- /src/mp-trigonometric.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1987-2008 Sun Microsystems, Inc. All Rights Reserved. 3 | * Copyright (C) 2008-2011 Robert Ancell. 4 | * 5 | * This program is free software: you can redistribute it and/or modify it under 6 | * the terms of the GNU General Public License as published by the Free Software 7 | * Foundation, either version 2 of the License, or (at your option) any later 8 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 9 | * license. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "mp.h" 18 | 19 | /* Convert x to radians */ 20 | void 21 | convert_to_radians(const MPNumber *x, MPAngleUnit unit, MPNumber *z) 22 | { 23 | int i; 24 | 25 | switch(unit) { 26 | default: 27 | case MP_RADIANS: 28 | mp_set_from_mp(x, z); 29 | return; 30 | 31 | case MP_DEGREES: 32 | i = 180; 33 | break; 34 | 35 | case MP_GRADIANS: 36 | i = 200; 37 | break; 38 | } 39 | mpfr_t scale; 40 | mpfr_init2(scale, PRECISION); 41 | mpfr_const_pi(scale, MPFR_RNDN); 42 | mpfr_div_si(scale, scale, i, MPFR_RNDN); 43 | mpc_mul_fr(z->num, x->num, scale, MPC_RNDNN); 44 | mpfr_clear(scale); 45 | } 46 | 47 | void 48 | convert_from_radians(const MPNumber *x, MPAngleUnit unit, MPNumber *z) 49 | { 50 | int i; 51 | 52 | switch(unit) { 53 | default: 54 | case MP_RADIANS: 55 | mp_set_from_mp(x, z); 56 | return; 57 | 58 | case MP_DEGREES: 59 | i = 180; 60 | break; 61 | 62 | case MP_GRADIANS: 63 | i = 200; 64 | break; 65 | } 66 | mpfr_t scale; 67 | mpfr_init2(scale, PRECISION); 68 | mpfr_const_pi(scale, MPFR_RNDN); 69 | mpfr_si_div(scale, i, scale, MPFR_RNDN); 70 | mpc_mul_fr(z->num, x->num, scale, MPC_RNDNN); 71 | mpfr_clear(scale); 72 | } 73 | 74 | void 75 | mp_get_pi (MPNumber *z) 76 | { 77 | mpfr_const_pi(mpc_realref(z->num), MPFR_RNDN); 78 | mpfr_set_zero(mpc_imagref(z->num), 0); 79 | } 80 | 81 | void 82 | mp_sin(const MPNumber *x, MPAngleUnit unit, MPNumber *z) 83 | { 84 | if (mp_is_complex(x)) 85 | mp_set_from_mp(x, z); 86 | else 87 | convert_to_radians(x, unit, z); 88 | mpc_sin(z->num, z->num, MPC_RNDNN); 89 | } 90 | 91 | void 92 | mp_cos(const MPNumber *x, MPAngleUnit unit, MPNumber *z) 93 | { 94 | if (mp_is_complex(x)) 95 | mp_set_from_mp(x, z); 96 | else 97 | convert_to_radians(x, unit, z); 98 | mpc_cos(z->num, z->num, MPC_RNDNN); 99 | } 100 | 101 | void 102 | mp_tan(const MPNumber *x, MPAngleUnit unit, MPNumber *z) 103 | { 104 | MPNumber x_radians = mp_new(); 105 | MPNumber pi = mp_new(); 106 | MPNumber t1 = mp_new(); 107 | 108 | convert_to_radians(x, unit, &x_radians); 109 | mp_get_pi(&pi); 110 | mp_divide_integer(&pi, 2, &t1); 111 | mp_subtract(&x_radians, &t1, &t1); 112 | mp_divide(&t1, &pi, &t1); 113 | 114 | if (mp_is_integer(&t1)) { 115 | /* Translators: Error displayed when tangent value is undefined */ 116 | mperr(_("Tangent is undefined for angles that are multiples of π (180°) from π∕2 (90°)")); 117 | mp_set_from_integer(0, z); 118 | mp_clear(&x_radians); 119 | mp_clear(&pi); 120 | mp_clear(&t1); 121 | return; 122 | } 123 | 124 | if (mp_is_complex(x)) 125 | mp_set_from_mp(x, z); 126 | else 127 | mp_set_from_mp(&x_radians, z); 128 | mpc_tan(z->num, z->num, MPC_RNDNN); 129 | mp_clear(&x_radians); 130 | mp_clear(&pi); 131 | mp_clear(&t1); 132 | } 133 | 134 | void 135 | mp_asin(const MPNumber *x, MPAngleUnit unit, MPNumber *z) 136 | { 137 | MPNumber x_max = mp_new(); 138 | MPNumber x_min = mp_new(); 139 | mp_set_from_integer(1, &x_max); 140 | mp_set_from_integer(-1, &x_min); 141 | 142 | if (mp_compare(x, &x_max) > 0 || mp_compare(x, &x_min) < 0) 143 | { 144 | /* Translators: Error displayed when inverse sine value is undefined */ 145 | mperr(_("Inverse sine is undefined for values outside [-1, 1]")); 146 | mp_set_from_integer(0, z); 147 | mp_clear(&x_max); 148 | mp_clear(&x_min); 149 | return; 150 | } 151 | mpc_asin(z->num, x->num, MPC_RNDNN); 152 | if (!mp_is_complex(z)) 153 | convert_from_radians(z, unit, z); 154 | mp_clear(&x_max); 155 | mp_clear(&x_min); 156 | } 157 | 158 | void 159 | mp_acos(const MPNumber *x, MPAngleUnit unit, MPNumber *z) 160 | { 161 | MPNumber x_max = mp_new(); 162 | MPNumber x_min = mp_new(); 163 | mp_set_from_integer(1, &x_max); 164 | mp_set_from_integer(-1, &x_min); 165 | 166 | if (mp_compare(x, &x_max) > 0 || mp_compare(x, &x_min) < 0) 167 | { 168 | /* Translators: Error displayed when inverse sine value is undefined */ 169 | mperr(_("Inverse cosine is undefined for values outside [-1, 1]")); 170 | mp_set_from_integer(0, z); 171 | mp_clear(&x_max); 172 | mp_clear(&x_min); 173 | return; 174 | } 175 | mpc_acos(z->num, x->num, MPC_RNDNN); 176 | if (!mp_is_complex(z)) 177 | convert_from_radians(z, unit, z); 178 | mp_clear(&x_max); 179 | mp_clear(&x_min); 180 | } 181 | 182 | void 183 | mp_atan(const MPNumber *x, MPAngleUnit unit, MPNumber *z) 184 | { 185 | MPNumber i = mp_new(); 186 | MPNumber minus_i = mp_new(); 187 | mpc_set_si_si(i.num, 0, 1, MPC_RNDNN); 188 | mpc_set_si_si(minus_i.num, 0, -1, MPC_RNDNN); 189 | 190 | /* Check x != i and x != -i */ 191 | if (mp_is_equal(x, &i) || mp_is_equal(x, &minus_i)) 192 | { 193 | /* Translators: Error displayed when inverse sine value is undefined */ 194 | mperr(_("Arctangent function is undefined for values i and -i")); 195 | mp_set_from_integer(0, z); 196 | mp_clear(&i); 197 | mp_clear(&minus_i); 198 | return; 199 | } 200 | mpc_atan(z->num, x->num, MPC_RNDNN); 201 | if (!mp_is_complex(z)) 202 | convert_from_radians(z, unit, z); 203 | mp_clear(&i); 204 | mp_clear(&minus_i); 205 | } 206 | 207 | void 208 | mp_sinh(const MPNumber *x, MPNumber *z) 209 | { 210 | mpc_sinh(z->num, x->num, MPC_RNDNN); 211 | } 212 | 213 | void 214 | mp_cosh(const MPNumber *x, MPNumber *z) 215 | { 216 | mpc_cosh(z->num, x->num, MPC_RNDNN); 217 | } 218 | 219 | void 220 | mp_tanh(const MPNumber *x, MPNumber *z) 221 | { 222 | mpc_tanh(z->num, x->num, MPC_RNDNN); 223 | } 224 | 225 | void 226 | mp_asinh(const MPNumber *x, MPNumber *z) 227 | { 228 | mpc_asinh(z->num, x->num, MPC_RNDNN); 229 | } 230 | 231 | void 232 | mp_acosh(const MPNumber *x, MPNumber *z) 233 | { 234 | MPNumber t = mp_new(); 235 | 236 | /* Check x >= 1 */ 237 | mp_set_from_integer(1, &t); 238 | if (mp_is_less_than(x, &t)) 239 | { 240 | /* Translators: Error displayed when inverse hyperbolic cosine value is undefined */ 241 | mperr(_("Inverse hyperbolic cosine is undefined for values less than one")); 242 | mp_set_from_integer(0, z); 243 | mp_clear(&t); 244 | return; 245 | } 246 | 247 | mpc_acosh(z->num, x->num, MPC_RNDNN); 248 | mp_clear(&t); 249 | } 250 | 251 | void 252 | mp_atanh(const MPNumber *x, MPNumber *z) 253 | { 254 | MPNumber x_max = mp_new(); 255 | MPNumber x_min = mp_new(); 256 | mp_set_from_integer(1, &x_max); 257 | mp_set_from_integer(-1, &x_min); 258 | 259 | if (mp_compare(x, &x_max) >= 0 || mp_compare(x, &x_min) <= 0) 260 | { 261 | /* Translators: Error displayed when inverse hyperbolic tangent value is undefined */ 262 | mperr(_("Inverse hyperbolic tangent is undefined for values outside (-1, 1)")); 263 | mp_set_from_integer(0, z); 264 | mp_clear(&x_max); 265 | mp_clear(&x_min); 266 | return; 267 | } 268 | mpc_atanh(z->num, x->num, MPC_RNDNN); 269 | mp_clear(&x_max); 270 | mp_clear(&x_min); 271 | } 272 | -------------------------------------------------------------------------------- /src/test-mp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008-2011 Robert Ancell. 3 | * 4 | * This program is free software: you can redistribute it and/or modify it under 5 | * the terms of the GNU General Public License as published by the Free Software 6 | * Foundation, either version 2 of the License, or (at your option) any later 7 | * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 8 | * license. 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "mp.h" 18 | 19 | static int fails = 0; 20 | static int passes = 0; 21 | 22 | /* If we're not using GNU C, elide __attribute__ */ 23 | #ifndef __GNUC__ 24 | # define __attribute__(x) /*NOTHING*/ 25 | #endif 26 | 27 | static void pass(const char *format, ...) __attribute__((format(printf, 1, 2))); 28 | static void fail(const char *format, ...) __attribute__((format(printf, 1, 2))); 29 | 30 | static void pass(const char *format, ...) 31 | { 32 | /* va_list args; 33 | 34 | printf(" PASS: "); 35 | va_start(args, format); 36 | vprintf(format, args); 37 | va_end(args); 38 | printf("\n"); 39 | */ 40 | passes += 1; 41 | } 42 | 43 | static void fail(const char *format, ...) 44 | { 45 | va_list args; 46 | 47 | printf("*FAIL: "); 48 | va_start(args, format); 49 | vprintf(format, args); 50 | va_end(args); 51 | printf("\n"); 52 | fails++; 53 | } 54 | 55 | static void 56 | print_number(MPNumber *x) 57 | { 58 | mpc_out_str(stdout, 10, 5, x->num, MPC_RNDNN); 59 | } 60 | 61 | static void 62 | test_string(const char *number) 63 | { 64 | MPNumber t = mp_new(); 65 | 66 | mp_set_from_string(number, 10, &t); 67 | 68 | printf("MPNumber(%s) -> {", number); 69 | print_number(&t); 70 | printf("}\n"); 71 | mp_clear(&t); 72 | } 73 | 74 | static void 75 | test_integer(int number) 76 | { 77 | MPNumber t = mp_new(); 78 | 79 | mp_set_from_integer(number, &t); 80 | 81 | printf("MPNumber(%d) -> {", number); 82 | print_number(&t); 83 | printf("}\n"); 84 | mp_clear(&t); 85 | } 86 | 87 | static void 88 | test_numbers(void) 89 | { 90 | test_integer(0); 91 | test_integer(1); 92 | test_integer(-1); 93 | test_integer(2); 94 | test_integer(9999); 95 | test_integer(10000); 96 | test_integer(10001); 97 | test_integer(2147483647); 98 | 99 | test_string("0"); 100 | test_string("1"); 101 | test_string("-1"); 102 | test_string("16383"); 103 | test_string("16384"); 104 | test_string("16385"); 105 | test_string("268435456"); 106 | 107 | test_string("0.1"); 108 | test_string("0.5"); 109 | test_string("0.25"); 110 | test_string("0.125"); 111 | test_string("0.0625"); 112 | test_string("0.00006103515625"); 113 | test_string("0.000030517578125"); 114 | 115 | test_string("1.00006103515625"); 116 | test_string("16384.00006103515625"); 117 | } 118 | 119 | static void 120 | try(const char *string, bool result, bool expected) 121 | { 122 | if ((result && !expected) || (!result && expected)) 123 | fail("%s -> %s, expected %s", string, expected ? "true" : "false", result ? "true" : "false"); 124 | else 125 | pass("%s -> %s", string, result ? "true" : "false"); 126 | } 127 | 128 | static void 129 | test_mp(void) 130 | { 131 | MPNumber zero = mp_new(); 132 | MPNumber one = mp_new(); 133 | MPNumber minus_one = mp_new(); 134 | mp_set_from_integer(0, &zero); 135 | mp_set_from_integer(1, &one); 136 | mp_set_from_integer(-1, &minus_one); 137 | 138 | try("mp_is_zero(-1)", mp_is_zero(&minus_one), false); 139 | try("mp_is_zero(0)", mp_is_zero(&zero), true); 140 | try("mp_is_zero(1)", mp_is_zero(&one), false); 141 | 142 | try("mp_is_negative(-1)", mp_is_negative(&minus_one), true); 143 | try("mp_is_negative(0)", mp_is_negative(&zero), false); 144 | try("mp_is_negative(1)", mp_is_negative(&one), false); 145 | 146 | try("mp_is_integer(-1)", mp_is_integer(&minus_one), true); 147 | try("mp_is_integer(0)", mp_is_integer(&zero), true); 148 | try("mp_is_integer(1)", mp_is_integer(&one), true); 149 | 150 | try("mp_is_positive_integer(-1)", mp_is_positive_integer(&minus_one), false); 151 | try("mp_is_positive_integer(0)", mp_is_positive_integer(&zero), true); 152 | try("mp_is_positive_integer(1)", mp_is_positive_integer(&one), true); 153 | 154 | try("mp_is_natural(-1)", mp_is_natural(&minus_one), false); 155 | try("mp_is_natural(0)", mp_is_natural(&zero), false); 156 | try("mp_is_natural(1)", mp_is_natural(&one), true); 157 | 158 | try("mp_is_complex(-1)", mp_is_complex(&minus_one), false); 159 | try("mp_is_complex(0)", mp_is_complex(&zero), false); 160 | try("mp_is_complex(1)", mp_is_complex(&one), false); 161 | 162 | try("mp_is_equal(-1, -1)", mp_is_equal(&minus_one, &minus_one), true); 163 | try("mp_is_equal(-1, 0)", mp_is_equal(&minus_one, &zero), false); 164 | try("mp_is_equal(-1, 1)", mp_is_equal(&minus_one, &one), false); 165 | try("mp_is_equal(0, -1)", mp_is_equal(&zero, &minus_one), false); 166 | try("mp_is_equal(0, 0)", mp_is_equal(&zero, &zero), true); 167 | try("mp_is_equal(0, 1)", mp_is_equal(&zero, &one), false); 168 | try("mp_is_equal(1, -1)", mp_is_equal(&one, &minus_one), false); 169 | try("mp_is_equal(1, 0)", mp_is_equal(&one, &zero), false); 170 | try("mp_is_equal(1, 1)", mp_is_equal(&one, &one), true); 171 | 172 | try("mp_is_greater_than(0, -1)", mp_is_greater_than (&zero, &minus_one), true); 173 | try("mp_is_greater_than(0, 0)", mp_is_greater_than (&zero, &zero), false); 174 | try("mp_is_greater_than(0, 1)", mp_is_greater_than (&zero, &one), false); 175 | try("mp_is_greater_than(1, -1)", mp_is_greater_than (&one, &minus_one), true); 176 | try("mp_is_greater_than(1, 0)", mp_is_greater_than (&one, &zero), true); 177 | try("mp_is_greater_than(1, 1)", mp_is_greater_than (&one, &one), false); 178 | try("mp_is_greater_than(-1, -1)", mp_is_greater_than (&minus_one, &minus_one), false); 179 | try("mp_is_greater_than(-1, 0)", mp_is_greater_than (&minus_one, &zero), false); 180 | try("mp_is_greater_than(-1, 1)", mp_is_greater_than (&minus_one, &one), false); 181 | 182 | try("mp_is_greater_equal(0, -1)", mp_is_greater_equal (&zero, &minus_one), true); 183 | try("mp_is_greater_equal(0, 0)", mp_is_greater_equal (&zero, &zero), true); 184 | try("mp_is_greater_equal(0, 1)", mp_is_greater_equal (&zero, &one), false); 185 | try("mp_is_greater_equal(1, -1)", mp_is_greater_equal (&one, &minus_one), true); 186 | try("mp_is_greater_equal(1, 0)", mp_is_greater_equal (&one, &zero), true); 187 | try("mp_is_greater_equal(1, 1)", mp_is_greater_equal (&one, &one), true); 188 | try("mp_is_greater_equal(-1, -1)", mp_is_greater_equal (&minus_one, &minus_one), true); 189 | try("mp_is_greater_equal(-1, 0)", mp_is_greater_equal (&minus_one, &zero), false); 190 | try("mp_is_greater_equal(-1, 1)", mp_is_greater_equal (&minus_one, &one), false); 191 | 192 | try("mp_is_less_than(0, -1)", mp_is_less_than (&zero, &minus_one), false); 193 | try("mp_is_less_than(0, 0)", mp_is_less_than (&zero, &zero), false); 194 | try("mp_is_less_than(0, 1)", mp_is_less_than (&zero, &one), true); 195 | try("mp_is_less_than(1, -1)", mp_is_less_than (&one, &minus_one), false); 196 | try("mp_is_less_than(1, 0)", mp_is_less_than (&one, &zero), false); 197 | try("mp_is_less_than(1, 1)", mp_is_less_than (&one, &one), false); 198 | try("mp_is_less_than(-1, -1)", mp_is_less_than (&minus_one, &minus_one), false); 199 | try("mp_is_less_than(-1, 0)", mp_is_less_than (&minus_one, &zero), true); 200 | try("mp_is_less_than(-1, 1)", mp_is_less_than (&minus_one, &one), true); 201 | 202 | try("mp_is_less_equal(0, -1)", mp_is_less_equal (&zero, &minus_one), false); 203 | try("mp_is_less_equal(0, 0)", mp_is_less_equal (&zero, &zero), true); 204 | try("mp_is_less_equal(0, 1)", mp_is_less_equal (&zero, &one), true); 205 | try("mp_is_less_equal(1, -1)", mp_is_less_equal (&one, &minus_one), false); 206 | try("mp_is_less_equal(1, 0)", mp_is_less_equal (&one, &zero), false); 207 | try("mp_is_less_equal(1, 1)", mp_is_less_equal (&one, &one), true); 208 | try("mp_is_less_equal(-1, -1)", mp_is_less_equal (&minus_one, &minus_one), true); 209 | try("mp_is_less_equal(-1, 0)", mp_is_less_equal (&minus_one, &zero), true); 210 | try("mp_is_less_equal(-1, 1)", mp_is_less_equal (&minus_one, &one), true); 211 | 212 | mp_clear(&zero); 213 | mp_clear(&one); 214 | mp_clear(&minus_one); 215 | } 216 | 217 | int 218 | main (void) 219 | { 220 | setlocale(LC_ALL, "C"); 221 | 222 | test_mp(); 223 | test_numbers(); 224 | if (fails == 0) 225 | printf("Passed all %i tests\n", passes); 226 | 227 | return fails; 228 | } 229 | --------------------------------------------------------------------------------