├── .gitignore ├── AUTHORS ├── COPYING ├── ChangeLog.old ├── Makefile.am ├── NEWS ├── README.md ├── THANKS ├── TODO ├── acinclude.m4 ├── configure.ac ├── data ├── Makefile.am ├── icons │ ├── 128x128 │ │ ├── Makefile.am │ │ └── yad.png │ ├── 16x16 │ │ ├── Makefile.am │ │ └── yad.png │ ├── 24x24 │ │ ├── Makefile.am │ │ └── yad.png │ ├── 32x32 │ │ ├── Makefile.am │ │ └── yad.png │ ├── 48x48 │ │ ├── Makefile.am │ │ └── yad.png │ ├── 96x96 │ │ ├── Makefile.am │ │ └── yad.png │ ├── Makefile.am │ └── meson.build ├── meson.build ├── misc │ ├── notify-send │ ├── pfd │ └── zenity.sh ├── yad-icon-browser.desktop.in ├── yad-tools.1 ├── yad.1 ├── yad.m4.in └── yad.spec.in ├── distributions.md ├── feature-comparison.md ├── meson.build ├── meson_options.txt ├── po ├── LINGUAS ├── POTFILES.in ├── de.po ├── es.po ├── fr.po ├── it.po ├── meson.build ├── pt_BR.po ├── ru.po ├── sk.po ├── uk.po └── zh_TW.po └── src ├── Makefile.am ├── about.c ├── browser.c ├── calendar.c ├── calendar.xpm ├── color.c ├── cpicker.c ├── cpicker.h ├── cpicker_gtk2.c ├── dnd.c ├── entry.c ├── file.c ├── font.c ├── form.c ├── html.c ├── icons.c ├── list.c ├── main.c ├── meson.build ├── notebook.c ├── notification.c ├── option.c ├── paned.c ├── picture.c ├── print.c ├── progress.c ├── scale.c ├── text.c ├── tools.c ├── util.c └── yad.h /.gitignore: -------------------------------------------------------------------------------- 1 | Makefile 2 | Makefile.in 3 | configure 4 | build/ 5 | autom4te.cache/ 6 | .deps/ 7 | *.o 8 | *~ 9 | \#*\# 10 | aclocal.m4 11 | config.h 12 | config.h.in 13 | config.log 14 | config.status 15 | data/yad-icon-browser.desktop 16 | data/yad.m4 17 | data/yad.spec 18 | po/.intltool-merge-cache 19 | po/Makefile.in.in 20 | po/POTFILES 21 | po/*.pot 22 | po/*.gmo 23 | po/stamp-it 24 | src/yad 25 | src/yad-icon-browser 26 | src/yad-tools 27 | stamp-h1 28 | *.tar.xz 29 | build.log 30 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Victor Ananjevsky 2 | 3 | Zenity Authors: 4 | Glynn Foster 5 | Mike Newman 6 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | SUBDIRS = src po data 3 | 4 | EXTRA_DIST = COPYING ChangeLog.old NEWS README.md AUTHORS TODO THANKS 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Yet Another Dialog -- GTK+-2 Maintenance Branch 2 | ==================== 3 | 4 | Use yad (yet another dialog) in shell scripts to displays GTK+ dialogs involving messages, lists, forms and several other commonly-used interface elements. 5 | 6 | Summary 7 | ------- 8 | 9 | [This](https://github.com/step-/yad) project is an independent fork of the [parent project](https://github.com/v1cont/yad). 10 | 11 | This project is licensed under the GNU GPL3 license, see _License and copyright_ section in [this page](feature-comparison.md). 12 | 13 | Project goals: 14 | 15 | * Overwhelmingly, maintain compatibility with GTK+-2. 16 | * Build against either GTK+-2 or GTK+-3. The two builds provide the same features. 17 | * Backport features from the parent project. 18 | * Introduce original features. 19 | 20 | 100% compatibility with the parent project is not a goal but keeping reasonably compatible still informs my decisions. 21 | [Feature comparison](feature-comparison.md) 22 | 23 | Several Linux [distributions](distributions.md) that still depend on GTK+-2 include a binary derived from this fork. 24 | 25 | History 26 | ------- 27 | 28 | The parent project removed GTK+-2 support in version 1.0. 29 | This repository was forked from the 0.42.0 release (d0021d0 February 2019) with the goal to continue GTK+-2 support, mainly for the benefit of the [Fatdog64](http://distro.ibiblio.org/fatdog/web/) Linux distribution. 30 | With time this fork has reached several other Linux [distributions](distributions.md) that need a GTK+-2 yad package. 31 | 32 | Scope 33 | ----- 34 | 35 | In the spirit of a maintainance project, fixing bugs takes precedence. 36 | New features can be added as my time permits but only if they are tested with, and work equally well for, GTK+-2 and GTK+-3. 37 | New features are introduced as either backports from the parent project or, more rarely, as original features. You can read all about this in the [feature comparison](feature-comparison.md) page. 38 | 39 | Contributions and pull requests (PR) are always welcome! 40 | 41 | Naming Hell 42 | ----------- 43 | 44 | This repository is named `yad`, same as its parent project's. Both projects build a binary file named `yad`. 45 | [Fatdog64](http://distro.ibiblio.org/fatdog/web/) renames the binary `yad_gtk2` or `yad_gtk3`, according to the build, and only ships `yad_gtk2`, with a symbolic link in /usr/bin from name `yad` to target `yad_gtk2`. The Fatdog64 package repository provides packages `yad_gtk2`, `yad_gtk3`, `yad_doc` and `yad_ultimate`, which is Fatdog64's package name for the parent project (and the parent project's binary is named `yadu`). 46 | 47 | For short I will use **yadL** for the products of this fork, and **yadU** for the parent project. 48 | 49 | Building yadL from Git 50 | ---------------------- 51 | 52 | This fork's default branch is named `maintain-gtk2`. All development takes place in the default branch. 53 | 54 | Get the latest source code with command: 55 | 56 | ```sh 57 | git clone https://github.com/step-/yad.git maintain-gtk2 58 | ``` 59 | 60 | Generate build scripts, configure and build the project: 61 | 62 | ```sh 63 | cd maintain-gtk2 && 64 | git checkout maintain-gtk2 && 65 | autoreconf -ivf && 66 | intltoolize && 67 | ./configure && 68 | make && 69 | : install with: make install 70 | ``` 71 | 72 | To build successfully you may need to install the following packages: 73 | 74 | * GNU Autotools (https://www.gnu.org/software/autoconf/ http://www.gnu.org/software/automake/) 75 | * Intltool >= 0.40.0 (http://freedesktop.org/wiki/Software/intltool/) 76 | * GTK+-2 >= 2.24.0 (http://www.gtk.org) 77 | * GTK+-3 >= 3.22.0 (http://www.gtk.org) 78 | 79 | with appropriate *-dev* packages depending on your distro. 80 | 81 | When you run `configure` you can pass some options to build yad with the following libraries: 82 | 83 | * GtkSourceView - for syntax highlighting in the text-info dialog (https://wiki.gnome.org/Projects/GtkSourceView) 84 | * GtkSpell3 - for spell checkinging text fields (http://gtkspell.sourceforge.net/) 85 | * Webkit - for the HTML dialog widget (http://webkitgtk.org) 86 | 87 | Distributions 88 | ------------- 89 | 90 | Distributions known to package this fork: read [distributions](distributions). 91 | 92 | Links 93 | ----- 94 | 95 | * [yadL development](https://github.com/step-/yad) 96 | * [yadL wiki](https://github.com/step-/yad/wiki) 97 | * [yad thread on Puppy Linux old forum](https://forum.puppylinux.com/viewtopic.php?t=216) 98 | * [yad thread on Puppy Linux forum](https://forum.puppylinux.com/viewtopic.php?t=3922) 99 | * [yadU development](https://github.com/v1cont/yad) 100 | * [yadU complex examples](https://github.com/v1cont/yad/wiki/YAD-Examples) 101 | * [yadU mailing list](http://groups.google.com/group/yad-common) 102 | 103 | -------------------------------------------------------------------------------- /THANKS: -------------------------------------------------------------------------------- 1 | "Zenity Authors", 2 | "=======", 3 | "Glynn Foster ", 4 | "Mike Newman ", 5 | "", 6 | "Patches from the following people", 7 | "=================================", 8 | "Darren Adams " 9 | "Timo Aaltonen ", 10 | "Peter Astrand ", 11 | "Jonathan Blandford ", 12 | "Paul Bolle ", 13 | "Paolo Borelli ", 14 | "Leonardo Boshell

", 15 | "Ross Burton ", 16 | "Damien Carbery ", 17 | "Anders Carlsson ", 18 | "Ed Catmur ", 19 | "Nicholas Curran ", 20 | "John Fleck ", 21 | "Sebastian Heinlein ", 22 | "James Henstridge ", 23 | "Chris Lahey ", 24 | "Mihai T Lazarescu ", 25 | "Sebastian Kapfer ", 26 | "Tomasz Koczko ", 27 | "Jordi Mallach ", 28 | "Kjartan Maraas ", 29 | "Breda McColgan ", 30 | "Baptiste Mille-Mathias ", 31 | "Buhan Milne ", 32 | "Christian Monneckes ", 33 | "Ivan Noris ", 34 | "Carlos Parra ", 35 | "Havoc Pennington ", 36 | "Jan Arne Petersen ", 37 | "Kevin C Krinke ", 38 | "Sriram Ramkrishna ", 39 | "Kristian Rietveld ", 40 | "Lucas Rocha ", 41 | "Christian Rose ", 42 | "Jakub Steiner ", 43 | "Luke Suchocki ", 44 | "Daniel d'Surreal ", 45 | "Hidetoshi Tajima ", 46 | "Tom Tromey ", 47 | "Yann ", 48 | "Norman Rasmussen ", 49 | "Benoît Dejean ", 50 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | - add actions to list, text-info and icons dialogs 2 | - use optional gtksourceview in text-info dialog (done) 3 | - add slideshow to picture dialog (reading uris from stdin) 4 | - add single model for completion and combo-boxes 5 | - add menu for select encodings in html dialog 6 | - add reverse check column for list dialog 7 | - add option for output format of boolean values (upper, lower, num) 8 | - add tooltips for labels 9 | - add custom handlers for edit and delete actions in editable lists 10 | -------------------------------------------------------------------------------- /acinclude.m4: -------------------------------------------------------------------------------- 1 | dnl Disable deprecated GTK+ features 2 | AC_DEFUN([GTK_DISABLE_DEPRECATED], 3 | [ 4 | AC_ARG_ENABLE(deprecated, [AC_HELP_STRING([--disable-deprecated], 5 | [Disable deprecated GTK functions])], 6 | ,[enable_deprecated=yes]) 7 | 8 | 9 | if test x$enable_deprecated = xyes 10 | then 11 | DISABLE_DEPRECATED= 12 | else 13 | DISABLE_DEPRECATED="-DG_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED -DGDK_PIXBUF_DISABLE_DEPRECATED -DPANGO_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED -DGSEAL_ENABLE" 14 | fi 15 | 16 | AC_SUBST(DISABLE_DEPRECATED) 17 | ]) 18 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # write PACKAGE_URL as "http" not "https" for About dialog to display a clickable link in the Credits tab. 2 | AC_INIT([YAD], [0.42.81], [https://github.com/step-/yad/issues], yad, [http://github.com/step-/yad]) 3 | AC_CONFIG_AUX_DIR([build]) 4 | 5 | AM_INIT_AUTOMAKE([1.11 foreign dist-xz no-dist-gzip]) 6 | AM_SILENT_RULES([yes]) 7 | 8 | AC_PREREQ([2.59]) 9 | 10 | AC_CONFIG_HEADERS([config.h]) 11 | AC_CONFIG_SRCDIR([src]) 12 | 13 | AM_MAINTAINER_MODE 14 | 15 | IT_PROG_INTLTOOL([0.40.0]) 16 | 17 | AC_PROG_CC 18 | 19 | AC_ARG_WITH([gtk], 20 | [AS_HELP_STRING([--with-gtk=gtk2|gtk3],[set the GTK+ version to use (default - gtk2)])], 21 | [case "$with_gtk" in 22 | gtk2|gtk3) ;; 23 | *) AC_MSG_ERROR([invalid gtk version specified]) ;; 24 | esac], 25 | [with_gtk=gtk2]) 26 | 27 | case "$with_gtk" in 28 | gtk3) 29 | GTK_MODULE="gtk+-3.0" 30 | GTK_REQUIRED="3.22.0" 31 | GTK_PRINT="gtk+-unix-print-3.0" 32 | WEBKIT="webkit2gtk-4.0" 33 | SPELL="gtkspell3-3.0" 34 | SOURCEVIEW="gtksourceview-3.0" 35 | ;; 36 | gtk2) 37 | GTK_MODULE="gtk+-2.0" 38 | GTK_REQUIRED="2.24.0" 39 | GTK_PRINT="gtk+-unix-print-2.0" 40 | WEBKIT="webkit-1.0" 41 | SPELL="gtkspell3-2.0" 42 | SOURCEVIEW="gtksourceview-2.0" 43 | ;; 44 | esac 45 | PKG_CHECK_MODULES([GTK], [$GTK_MODULE >= $GTK_REQUIRED $GTK_PRINT]) 46 | AC_SUBST([GTK_CFLAGS]) 47 | AC_SUBST([GTK_LIBS]) 48 | AM_CONDITIONAL([GTK2], [test x$with_gtk = xgtk2]) 49 | 50 | GTK_DISABLE_DEPRECATED 51 | 52 | dnl rgb.txt 53 | AC_ARG_WITH([rgb], 54 | [AS_HELP_STRING([--with-rgb=PATH], 55 | [set path to rgb.txt file (default - /etc/X11/rgb.txt)])], 56 | [with_rgb=$withval], [with_rgb=/etc/X11/rgb.txt]) 57 | AC_DEFINE_UNQUOTED([RGB_FILE], ["$with_rgb"], [Path to rgb.txt file]) 58 | 59 | dnl html widget 60 | AC_ARG_ENABLE([html], 61 | [AS_HELP_STRING([--enable-html], 62 | [Build YAD with HTML widget])], 63 | [build_html=$enableval], [build_html=yes]) 64 | if test x$build_html = xyes; then 65 | PKG_CHECK_MODULES([HTML], [$WEBKIT], [have_html=yes], [have_html=no]) 66 | else 67 | have_html=no 68 | fi 69 | AC_SUBST([HTML_CFLAGS]) 70 | AC_SUBST([HTML_LIBS]) 71 | AM_CONDITIONAL([HTML], [test x$have_html = xyes]) 72 | 73 | if test x$have_html = xyes; then 74 | AC_DEFINE([HAVE_HTML], [1], [Define this if you have webkit installed]) 75 | if test x$with_gtk = xgtk3; then 76 | AC_DEFINE([USE_WEBKIT2], [1], [Define this if you use webkit2 API]) 77 | fi 78 | fi 79 | 80 | dnl gio support 81 | AC_ARG_ENABLE([gio], 82 | [AS_HELP_STRING([--enable-gio], 83 | [Build YAD with GIO support])], 84 | [build_gio=$enableval], [build_gio=yes]) 85 | if test x$build_gio = xyes; then 86 | PKG_CHECK_MODULES([GIO], [gio-2.0], [have_gio=yes], [have_gio=no]) 87 | else 88 | have_gio=no 89 | fi 90 | AC_SUBST([GIO_CFLAGS]) 91 | AC_SUBST([GIO_LIBS]) 92 | 93 | if test x$have_gio = xyes; then 94 | AC_DEFINE([HAVE_GIO], [1], [Define this if you have glib gio framework]) 95 | fi 96 | 97 | dnl status icon widget 98 | AC_ARG_ENABLE([tray], 99 | [AS_HELP_STRING([--enable-tray], 100 | [Build YAD with status icon])], 101 | [build_tray=$enableval], [build_tray=yes]) 102 | AM_CONDITIONAL([TRAY], [test x$build_tray = xyes]) 103 | 104 | if test x$build_tray = xyes; then 105 | AC_DEFINE([HAVE_TRAY], [1], [Define this if you need status icon]) 106 | fi 107 | 108 | dnl spell check 109 | AC_ARG_ENABLE([spell], 110 | [AS_HELP_STRING([--enable-spell], 111 | [Build YAD with Spell check support (default - no)])], 112 | [with_spell=$enableval], [with_spell=no]) 113 | if test x$with_spell = xyes; then 114 | PKG_CHECK_MODULES([SPELL], [$SPELL], [have_spell=yes], [have_spell=no]) 115 | else 116 | have_spell=no 117 | fi 118 | AC_SUBST([SPELL_CFLAGS]) 119 | AC_SUBST([SPELL_LIBS]) 120 | 121 | if test x$have_spell = xyes; then 122 | AC_DEFINE([HAVE_SPELL], [1], [Define this if you need spell check support]) 123 | fi 124 | 125 | dnl sourceview 126 | AC_ARG_ENABLE([sourceview], 127 | [AS_HELP_STRING([--enable-sourceview], 128 | [Build YAD with GtkSourceView support (default - no)])], 129 | [with_sourceview=$enableval], [with_sourceview=no]) 130 | if test x$with_sourceview = xyes; then 131 | PKG_CHECK_MODULES([SOURCEVIEW], [$SOURCEVIEW], [have_sourceview=yes], [have_sourceview=no]) 132 | else 133 | have_sourceview=no 134 | fi 135 | AC_SUBST([SOURCEVIEW_CFLAGS]) 136 | AC_SUBST([SOURCEVIEW_LIBS]) 137 | 138 | if test x$have_sourceview = xyes; then 139 | AC_DEFINE([HAVE_SOURCEVIEW], [1], [Define this if you need GtkSourceView support]) 140 | fi 141 | 142 | dnl tools 143 | AC_ARG_ENABLE([tools], 144 | [AS_HELP_STRING([--enable-tools], 145 | [Build yad-tools utility])], 146 | [build_tools=$enableval], [build_tools=yes]) 147 | AM_CONDITIONAL([BUILD_TOOLS], [test x$build_tools = xyes]) 148 | 149 | dnl icon browser 150 | AC_ARG_ENABLE([icon-browser], 151 | [AS_HELP_STRING([--enable-icon-browser], 152 | [Build YAD icon browser])], 153 | [build_ib=$enableval], [build_ib=yes]) 154 | AM_CONDITIONAL([BUILD_IB], [test x$build_ib = xyes]) 155 | 156 | AC_SEARCH_LIBS(round, m) 157 | 158 | # ******************************* 159 | # Internationalization 160 | # ******************************* 161 | 162 | GETTEXT_PACKAGE=yad 163 | AC_SUBST([GETTEXT_PACKAGE]) 164 | AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE], ["$GETTEXT_PACKAGE"], [Gettext domain]) 165 | 166 | AM_GLIB_GNU_GETTEXT 167 | 168 | # ******************************* 169 | 170 | AC_SUBST([AM_CFLAGS]) 171 | AC_SUBST([AM_CPPFLAGS]) 172 | AC_SUBST([AM_LDFLAGS]) 173 | 174 | # ******************************* 175 | 176 | AC_CONFIG_FILES([ 177 | Makefile 178 | po/Makefile.in 179 | src/Makefile 180 | data/Makefile 181 | data/icons/Makefile 182 | data/icons/16x16/Makefile 183 | data/icons/24x24/Makefile 184 | data/icons/32x32/Makefile 185 | data/icons/48x48/Makefile 186 | data/icons/96x96/Makefile 187 | data/icons/128x128/Makefile 188 | data/yad.m4 189 | data/yad.spec 190 | ]) 191 | 192 | AC_OUTPUT 193 | 194 | echo 195 | echo "Build configuration:" 196 | echo " GTK+ version - $with_gtk" 197 | echo " Path to rgb.txt - $with_rgb" 198 | echo " Status icon - $build_tray" 199 | echo " HTML widget - $have_html" 200 | echo " Spell checking - $have_spell" 201 | echo " GtkSourceView - $have_sourceview" 202 | echo " GIO support - $have_gio" 203 | echo " Tools - $build_tools" 204 | echo " Icon browser - $build_ib" 205 | echo 206 | -------------------------------------------------------------------------------- /data/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = icons 2 | 3 | desktop_in_files = yad-icon-browser.desktop.in 4 | if BUILD_IB 5 | desktopdir = $(datadir)/applications 6 | desktop_DATA = $(desktop_in_files:.desktop.in=.desktop) 7 | @INTLTOOL_DESKTOP_RULE@ 8 | endif 9 | 10 | dist_man_MANS = yad.1 11 | if BUILD_TOOLS 12 | dist_man_MANS += yad-tools.1 13 | endif 14 | 15 | m4dir = $(datadir)/aclocal 16 | m4_DATA = yad.m4 17 | 18 | EXTRA_DIST = $(desktop_in_files) misc 19 | 20 | DISTCLEANFILES = $(desktop_DATA) $(m4_DATA) yad.spec 21 | -------------------------------------------------------------------------------- /data/icons/128x128/Makefile.am: -------------------------------------------------------------------------------- 1 | iconsdir = $(datadir)/icons/hicolor/128x128/apps 2 | dist_icons_DATA = yad.png 3 | -------------------------------------------------------------------------------- /data/icons/128x128/yad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/step-/yad/cfe6c7064f3daff80953a09a890537a8e68b8d11/data/icons/128x128/yad.png -------------------------------------------------------------------------------- /data/icons/16x16/Makefile.am: -------------------------------------------------------------------------------- 1 | iconsdir = $(datadir)/icons/hicolor/16x16/apps 2 | dist_icons_DATA = yad.png 3 | -------------------------------------------------------------------------------- /data/icons/16x16/yad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/step-/yad/cfe6c7064f3daff80953a09a890537a8e68b8d11/data/icons/16x16/yad.png -------------------------------------------------------------------------------- /data/icons/24x24/Makefile.am: -------------------------------------------------------------------------------- 1 | iconsdir = $(datadir)/icons/hicolor/24x24/apps 2 | dist_icons_DATA = yad.png 3 | -------------------------------------------------------------------------------- /data/icons/24x24/yad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/step-/yad/cfe6c7064f3daff80953a09a890537a8e68b8d11/data/icons/24x24/yad.png -------------------------------------------------------------------------------- /data/icons/32x32/Makefile.am: -------------------------------------------------------------------------------- 1 | iconsdir = $(datadir)/icons/hicolor/32x32/apps 2 | dist_icons_DATA = yad.png 3 | -------------------------------------------------------------------------------- /data/icons/32x32/yad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/step-/yad/cfe6c7064f3daff80953a09a890537a8e68b8d11/data/icons/32x32/yad.png -------------------------------------------------------------------------------- /data/icons/48x48/Makefile.am: -------------------------------------------------------------------------------- 1 | iconsdir = $(datadir)/icons/hicolor/48x48/apps 2 | dist_icons_DATA = yad.png 3 | -------------------------------------------------------------------------------- /data/icons/48x48/yad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/step-/yad/cfe6c7064f3daff80953a09a890537a8e68b8d11/data/icons/48x48/yad.png -------------------------------------------------------------------------------- /data/icons/96x96/Makefile.am: -------------------------------------------------------------------------------- 1 | iconsdir = $(datadir)/icons/hicolor/96x96/apps 2 | dist_icons_DATA = yad.png 3 | -------------------------------------------------------------------------------- /data/icons/96x96/yad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/step-/yad/cfe6c7064f3daff80953a09a890537a8e68b8d11/data/icons/96x96/yad.png -------------------------------------------------------------------------------- /data/icons/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = 16x16 24x24 32x32 48x48 96x96 128x128 2 | 3 | gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor 4 | 5 | install-data-hook: 6 | @-if test -z "$(DESTDIR)"; then \ 7 | echo "Updating Gtk icon cache."; \ 8 | $(gtk_update_icon_cache); \ 9 | else \ 10 | echo "*** Icon cache not updated. Remember to run:"; \ 11 | echo "***"; \ 12 | echo "*** $(gtk_update_icon_cache)"; \ 13 | echo "***"; \ 14 | fi 15 | 16 | uninstall-local: 17 | rm -f $(DESTDIR)$(datadir)/icons/hicolor/icon-theme.cache; 18 | -------------------------------------------------------------------------------- /data/icons/meson.build: -------------------------------------------------------------------------------- 1 | foreach size : [16, 24, 32, 48, 96, 128] 2 | install_data(f'@size@x@size@/yad.png', 3 | install_dir : f'share/icons/hicolor/@size@x@size@/apps') 4 | endforeach 5 | -------------------------------------------------------------------------------- /data/meson.build: -------------------------------------------------------------------------------- 1 | install_man('yad.1') 2 | 3 | subdir('icons') 4 | -------------------------------------------------------------------------------- /data/misc/notify-send: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | # Defaults 4 | APP="notification" 5 | TIMEOUT=600 6 | ICON="dialog-information" 7 | TITLE= 8 | BODY= 9 | 10 | # Parse command line 11 | OPTIND=1 12 | while getopts a:i:t: opt ; do 13 | case "$opt" in 14 | a) APP=$OPTARG ;; 15 | i) ICON=$OPTARG ;; 16 | t) TIMEOUT=$OPTARG ;; 17 | esac 18 | done 19 | shift $(($OPTIND - 1)) 20 | [[ "$1" == '--' ]] && shift 21 | 22 | TITLE="$1" 23 | shift 24 | BODY="$@" 25 | 26 | gdbus call --session --dest org.freedesktop.Notifications \ 27 | --object-path /org/freedesktop/Notifications \ 28 | --method org.freedesktop.Notifications.Notify \ 29 | "$APP" 0 "$ICON" "$TITLE" "$BODY" "[]" "{}" $TIMEOUT &> /dev/null 30 | -------------------------------------------------------------------------------- /data/misc/pfd: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "WARNING: pfd is deprecated. Please use yad-tools --pfd instead" >&2 4 | exec yad-tools --pfd "$@" 5 | -------------------------------------------------------------------------------- /data/misc/zenity.sh: -------------------------------------------------------------------------------- 1 | 2 | function zenity () 3 | { 4 | local ARGS 5 | ARGS= 6 | for a in "$@"; do 7 | case $a in 8 | --info) ARGS="$ARGS --image=gtk-dialog-info" ;; 9 | --question) ARGS="$ARGS --image=gtk-dialog-question" ;; 10 | --warning) ARGS="$ARGS --image=gtk-dialog-warning" ;; 11 | --error) ARGS="$ARGS --image=gtk-dialog-error" ;; 12 | *) ARGS="$ARGS $a" 13 | esac 14 | done 15 | eval set -- $ARGS 16 | yad $@ 17 | } 18 | export -f zenity 19 | -------------------------------------------------------------------------------- /data/yad-icon-browser.desktop.in: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Encoding=UTF-8 3 | _Name=Icon Browser 4 | _Comment=Inspect GTK Icon Theme 5 | Categories=GTK;Development; 6 | Exec=yad-icon-browser 7 | Icon=yad 8 | Terminal=false 9 | Type=Application 10 | StartupNotify=true 11 | -------------------------------------------------------------------------------- /data/yad-tools.1: -------------------------------------------------------------------------------- 1 | .TH YAD-TOOLS "1" "April 2021" "yad-tools" "User Commands" 2 | 3 | .SH NAME 4 | yad-tools \- show miscellaneous information. 5 | 6 | .SH SYNOPSIS 7 | .B yad-tools 8 | .RI [OPTIONS] 9 | .RI STRING 10 | 11 | .SH DESCRIPTION 12 | \fByad-tools\fR is a small command-line utility for getting information that may be useful in scripts. 13 | 14 | .SH OPTIONS 15 | 16 | .SS General options 17 | .TP 18 | \fB\-f\fR, \fB\-\-pfd\fR 19 | This mode is intended to transform font names from pango to xft specification and vice versa. 20 | Additional argument is a font name. 21 | .TP 22 | \fB\-i\fR, \fB\-\-icon\fR 23 | This mode is intended to get full path to icon file from icon name. 24 | Additional argument is an icon name. 25 | .TP 26 | \fB\-c\fR, \fB\-\-color\fR 27 | This mode is intended for working with colors. 28 | .TP 29 | .B \-\-show-langs 30 | Show list of available languages for spell checking. It only works if yad was built with \fIGtkspell3\fP support. 31 | .TP 32 | .B \-\-show-themes 33 | Show list of available GtkSourceView themes. It only works if yad was built with \fIGtkSourceView\fP support. 34 | 35 | .SS PFD mode options 36 | .TP 37 | \fB\-x\fR, \fB\-\-xft\fR 38 | Print font name in xft format. This is the default. 39 | .TP 40 | \fB\-p\fR, \fB\-\-pango\fR 41 | Print font name in pango format. 42 | 43 | .SS Icon mode options 44 | .TP 45 | \fB\-s\fR, \fB\-\-size\fR=\fISIZE\fP 46 | Use specified icon size. Default is 24. 47 | .TP 48 | \fB\-t\fR, \fB\-\-type\fR=\fITYPE\fP 49 | Obtain icon size from one of the predefined GTK+ types. \fITYPE\fP is one of the following \fImenu\fP, \fIbutton\fP, \fIsmall_toolbar\fP, \fIlarge_toolbar\fP, \fIdnd\fP or \fIdialog\fP. 50 | .TP 51 | \fB\-m\fR, \fB\-\-mime\fP 52 | Get generic icon name for specified mime type. 53 | .TP 54 | \fB\-\-theme\fR=\fITHEME\fP 55 | Use the specified icon theme instead of the default. 56 | 57 | .SS Color mode options 58 | .TP 59 | \fB\-\-pick\fP 60 | Pick screen pixel color. 61 | -------------------------------------------------------------------------------- /data/yad.m4.in: -------------------------------------------------------------------------------- 1 | ## -*- Autoconf -*- 2 | # 3 | # Copyright (c) 2008-2011, Vitor Ananjevsky 4 | # 5 | # This file is free software; the Free Software Foundation 6 | # gives unlimited permission to copy and/or distribute it, 7 | # with or without modifications, as long as this notice is preserved. 8 | 9 | # AM_PATH_YAD([MINIMUM-VERSION],[ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND]) 10 | # --------------------------------------------------------------------------- 11 | AC_DEFUN([AM_PATH_YAD],[ 12 | m4_if([$1],[],[ 13 | dnl No version check is needed. 14 | if test -z "$YAD"; then 15 | AC_PATH_PROG([YAD], yad, :) 16 | fi 17 | ], [ 18 | dnl A version check is needed. 19 | if test -z "$YAD"; then 20 | AC_PATH_PROG([YAD], yad, :) 21 | fi 22 | AC_MSG_CHECKING([whether yad version >= $1]) 23 | m4_define([yad_version],[@VERSION@]) 24 | m4_if(m4_version_compare(yad_version,[$1]),[-1], 25 | [AC_MSG_ERROR([too old (]yad_version[)])], 26 | [AC_MSG_RESULT(yad_version)]) 27 | ]) 28 | 29 | if test "$YAD" = :; then 30 | dnl Run any user-specified action, or abort. 31 | m4_default([$3], [AC_MSG_ERROR([Yad not found])]) 32 | else 33 | dnl Run any user-specified action. 34 | m4_if([$2],[],[true],[$2]) 35 | AC_SUBST([YAD]) 36 | fi 37 | ]) 38 | -------------------------------------------------------------------------------- /data/yad.spec.in: -------------------------------------------------------------------------------- 1 | # norootforbuild 2 | 3 | Name: yad 4 | Version: @VERSION@ 5 | Release: 1 6 | 7 | Summary: A fork of Zenity with many improvements 8 | License: GPLv3 9 | Group: Development/Tools/GUI Builders 10 | URL: http://code.google.com/p/yad/ 11 | 12 | Source0: %{name}-%{version}.tar.bz2 13 | 14 | BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot 15 | 16 | BuildRequires: gtk2-devel intltool pkgconfig 17 | 18 | 19 | %description 20 | Yad (yet another dialog) is a fork of Zenity with many improvements, such as 21 | custom buttons, additional dialogs, pop-up menu in notification icon and more. 22 | 23 | There were two main reasons to make this fork. The first one is to remove 24 | dependencies on deprecated libraries, such as libglade and gnome-canvas. 25 | And the second one - as for me, Zenity looks like an abandoned project. 26 | Its ChangeLog consists of just "bump version to..." and "translation updated" 27 | for the long time, but many interesting ideas which are ignored by 28 | developers/maintainers were in GNOME Bugzilla. 29 | 30 | 31 | %debug_package 32 | 33 | 34 | %prep 35 | %setup -q -n %{name}-%{version} 36 | 37 | 38 | %build 39 | %configure 40 | %__make %{?jobs:-j%{jobs}} 41 | 42 | 43 | %install 44 | %makeinstall 45 | %find_lang %{name} 46 | 47 | 48 | %clean 49 | rm -rf "%{buildroot}" 50 | 51 | 52 | %files -f %{name}.lang 53 | %defattr(-,root,root,-) 54 | %doc AUTHORS ChangeLog COPYING README THANKS TODO 55 | %{_bindir}/%{name} 56 | %{_datadir}/pixmaps/%{name}.png 57 | %{_mandir}/man1/%{name}.1.gz 58 | 59 | 60 | %changelog 61 | * Tue Jan 05 2010 - Detlef Reichelt - 0.0.8 62 | - initial build for PackMan <0.0.8> 63 | -------------------------------------------------------------------------------- /distributions.md: -------------------------------------------------------------------------------- 1 | # DISTRIBUTIONS KNOWN TO PACKAGE THIS FORK 2 | 3 | * Fatdog64 Linux: https://distro.ibiblio.org/fatdog/web/ 4 | * EasyOS, from version 3.0 onwards: https://easyos.org, [recipe](https://github.com/bkauler/oe-qky-dunfell/tree/main/quirky/meta-quirky/recipes-quirky/yad0) 5 | * Woof, the Puppy Linux builder: https://github.com/puppylinux-woof-CE/woof-CE, [recipe](https://github.com/puppylinux-woof-CE/woof-CE/tree/testing/woof-code/rootfs-petbuilds/yad) 6 | 7 | -------------------------------------------------------------------------------- /feature-comparison.md: -------------------------------------------------------------------------------- 1 | # COMPARISON BETWEEN THIS FORK AND ITS PARENT PROJECT 2 | 3 | For short, I will use **yadL** for the products of this fork, and **yadU** for the parent project's. [More info](README.md) 4 | 5 | yadL version number is formed as 0.42.x where integer "x" indicates some released progress worth mentioning. 6 | 7 | Numbered notes are grouped together at the end of this long page. 8 | 9 | ## Licence and copyright 10 | 11 | GNU GPL3 is license to both yadL and yadU. Copyright notices in yadL source code are not always up-to-date. To comply with GPL3's license I hereby claim copyright on the source code added to this repository: 12 | 13 | yad maintenance branch, aka yad-maintain-gtk2, yadL, (C) 2019-2023 step 14 | 15 | ## New yadL features 16 | 17 | yadL of its own adds the following new features not included in yadU, to the best of my knowledge. 18 | Refer to [yadL commit log](https://github.com/step-/yad/commits) for more details. 19 | See also [Preparing yadL scripts for yadU](https://github.com/step-/yad/wiki/Preparing-yadL-scripts-for-yadU) in the yadL Wiki. 20 | 21 | - option `--icon-width=SIZE` is a deprecated alias for `--icon-size` 22 | - new option `--center-keep` 23 | - yadL GTK+-3 binary still supports stock items for button icons 24 | - yadL still uses the GtkSpell3 spell engine 25 | - yadL's own about dialog is modified 26 | - save print settings to new file `$XDG_CONFIG_HOME/yad/print.conf` ⁽⁵⁾ 27 | 28 | (§)N Refers to our pull request (PR) number N [https://github.com/v1cont/yad/pulls?q=author%3Astep-](https://github.com/v1cont/yad/pulls?q=author%3Astep-). 29 | 30 | - symbolic ID field references in form dialog actions [0.42.71] (§)213 31 | - symbolic ID names in form dialog output [0.42.71] (§)213 32 | - auto-disable form buttons and list items while synchronous action runs [0.42.73] (§)221 33 | 34 | ## Notable bug fixes 35 | 36 | Several bugs that affected the parent project when it was forked have been fixed. The following stand out: 37 | 38 | * some print dialog issues⁽¹⁾ [0.42.38] 39 | * forcefully close a notebook dialog on exit if some tab has hung 40 | * unpredictably, notebook tabs are too small [0.42.43] 41 | * form button syntax [0.42.75] 42 | 43 | ## Known bugs 44 | 45 | * (GTK+-2 build only) If the main icon of the notification dialog is a named icon, it does not scale automatically, therefore it looks larger than other icons in the tray. This bug has existed since at least version 0.40.0. It can only be noticed on some notification trays that do not themselves resize the icons they display. 46 | 47 | ## Frozen or untested features 48 | 49 | * HTML dialog widget - As Fatdog64 Linux no longer packages the Webkit engine, I do not make an effort to maintain or even compile yadL's HTML dialog widget. 50 | 51 | ## Diverged features 52 | 53 | See the _New yadL features_ and _Notes_ sections. 54 | 55 | ## Features and bug fixes backported from yadU to yadL 56 | 57 | [This list](https://github.com/step-/blob/maintain-gtk2/feature-comparison.md) 58 | of yadU features is extracted from the [NEWS](https://github.com/v1cont/NEWS) file. 59 | 60 | The version numbers in the following headings refer to yadU releases. 61 | My annotations are wrapped in square brackets. The version numbers refer to yadL releases. 62 | (§)N Refers to our pull request (PR) number N [https://github.com/v1cont/yad/pulls?q=author%3Astep-](https://github.com/v1cont/yad/pulls?q=author%3Astep-). 63 | 64 | Abbreviations: 65 | 66 | * `[+]` the feature is backported therefore available in yadL 67 | * `[>]` the feature will not be backported as it depends on capabilities that are not available in GTK+-2 68 | * `[-]` the feature will not be backported (reason may vary) 69 | * `[!]` the feature will not be backported because it is incompatible with the yadL souce code base (diverged feature) 70 | * `[ ]` the feature is undecided, not yet evaluated for backporting, etc. 71 | * `[?]` the feature is being evaluated for backporting 72 | 73 | --- 74 | 75 | Version 12.4? (yadU WIP) 76 | 77 | - `[+]` 2210136 fix option parsing in icon browser [0.42.78] 78 | - `[+]` d7ded23 improve run\_command\_sync for avoiding possible race conditions [0.42.67] 79 | - `[+]` 1d402f7 add some null-pointer checks in form dialog code [0.42.67] 80 | - `[+]` ff81778 remove some warnings [0.42.66] 81 | - `[+]` c8e9ef2 fix UI not updated when sync command runs [0.42.66] (§)210 82 | 83 | Version 12.3 84 | 85 | - `[ ]` fixed setting webkit properties and user defined style sheet in html dialog 86 | - `[ ]` improve stdin handler for html dialog 87 | - `[ ]` update copyright notice 88 | 89 | Version 12.2 90 | 91 | - `[ ]` add --auto-scroll option as an alias to --tail 92 | - `[ ]` fixed jump to anchor in simple mode of html dialog 93 | - `[?]` fixed parsing data from stdin for tree mode of list dialog 94 | - `[ ]` fixed man page 95 | - `[ ]` code cleanup 96 | 97 | Version 12.1 98 | 99 | - `[ ]` fixed some typos 100 | - `[ ]` fixed permissions in thumbnails creation 101 | - `[ ]` improve interpreteur string in yad-settings script 102 | 103 | Version 12.0 104 | 105 | - `[ ]` add ability to load several images in picture dialog 106 | - `[+]` add color picker to color dialog and yad-tools [0.42.68],[0.42.72] 107 | - `[ ]` add --line option to text-info dialog 108 | - `[ ]` improve guess of syntax highlighting in text-info dialog 109 | - `[+]` add --mime option to icon mode in yad-tools ⁽¹¹⁾ [0.42.68] 110 | - `[+]` add switch field type in form dialog (thanks to Misko ) [0.42.54] 111 | - `[ ]` use pango markup for multiline text field in form dialog 112 | 113 | Version 11.1 114 | 115 | - `[ ]` fix input parsing for notification icon 116 | - `[ ]` fix parsing desktop files for icons dialog 117 | - `[ ]` fix link handling for browser mode in html dialog 118 | - `[ ]` improve setting user-defined image in about dialog 119 | 120 | Version 11.0 121 | 122 | - `[ ]` DROP K HUJAM russian translation 123 | - `[?]` for other changes please discover the git changelog 124 | 125 | Version 10.1 126 | 127 | - `[+]` don't make rows homogeneous when form has a text field [0.52.53] +form option --homogeneous 128 | 129 | Version 10.0 130 | 131 | - `[ ]` many improvements in text-info dialog 132 | - `[+]` uses monospace font by default [0.42.76] 133 | - `[ ]` added search-bar instead of popup search field (can be disabled) 134 | - `[ ]` added more GtkSourceView capabilities (use --help-source to see full list of those options) 135 | - `[ ]` added in-place editing and file operations throug popup menu or keybindings 136 | - `[ ]` added search bar to html dialog (can be disabled) 137 | - `[ ]` added Ctrl+O and Ctrl+Q shortcuts to html dialog 138 | - `[ ]` added --f1-action which run command when F1 was pressed 139 | - `[+]` added --changed-action to form dialog for control states of switcher fields like check or combo boxes [0.42.52] 140 | - `[ ]` fixed build with musl 141 | - `[ ]` added yad-settings script. this is yad-based frontend for edit yad settings 142 | - `[ ]` force using small icons in list dialog if icon is not a real filename 143 | - `[ ]` fixed fitting image in picture dialog 144 | 145 | Version 9.3 146 | 147 | - `[+]` fix freezing main window on --row-action in list or @cmd in form dialogs [0.42.56] 148 | 149 | Version 9.2 150 | 151 | - `[ ]` some fixes of menu in editable lists 152 | - `[ ]` add two additional item to menu in editable lists - "move up" and "move down" 153 | - `[+]` use double quotes for arguments in default interpreter command [0.42.61] 154 | 155 | Version 9.1 156 | 157 | - `[?]` fix --version option 158 | 159 | Version 9.0 160 | 161 | - `[ ]` implement user's customizable --about dialog 162 | - `[?]` fix passing focus to children in notebook and paned dialogs 163 | - `[ ]` add --stack mode to notebook dialog 164 | - `[?]` add --focused option to paned dialog for selectin focused pane 165 | - `[?]` don't vertically expand entry in entry dialog 166 | - `[?]` fix setting splitter position in paned dialog 167 | - `[ ]` add --wk-prop to html dialog and made js output enabled by default 168 | - `[+]` replace yad-tools for pfd utility. pfd remains as a compatibility wrapper script [0.42.68] 169 | - `[+]` add --align-buttons option for aligning labels on button fields in form dialog [0.42.50] 170 | 171 | 172 | - `[?]` add --text-width option for more flexible wrapping long strings in dialog text 173 | - `[ ]` handle URIs in dialog text 174 | - `[>]` add --css option (--gtkrc marked as deprecated) 175 | - `[ ]` lots of bug fixes 176 | 177 | Version 7.3 178 | 179 | - `[+]` fix parsing separator field for form dialog (thanks to Dmitry Butskoy) 180 | - `[ ]` fix handling user defined size of dialog with --width and --height arguments 181 | 182 | Version 7.2 183 | 184 | - `[+]` fix parsing field names for form dialog 185 | - `[+]` fix uri-handler for html dialog [0.42.46] 186 | - `[ ]` add file: scheme for uri regexp in text-info dialog 187 | 188 | Version 7.1 189 | 190 | - `[+]` fix parsing field names for form dialog 191 | 192 | Version 7.0 193 | 194 | - `[+]` add --enforce-step option to scale dialog [0.42.62] 195 | - `[+]` add tooltips and markup to column headers in list dialog [0.42.63] 196 | - `[-]` add pango-style font definition to text-info dialog ⁽⁷⁾ 197 | - `[+]` add --large-preview options for better thumbnails handling ⁽⁵⁾⁽⁹⁾ [0.42.64] 198 | - `[+]` add --interactive option to icon browser to print selected icon to stdout [0.42.66] 199 | - `[+]` add custom uri handler (--uri-handler option) [0.42.46] 200 | - `[+]` improve killing children algo for notebook and paned dialogs 201 | - `[+]` add tooltips for form fields [0.42.48] 202 | - `[+]` fix :tip column in list dialog [0.42.66] 203 | - `[+]` fixes and cleanups in miscellaneous functions [0.42.46] 204 | - `[+]` fix parsing numeric ranges in form dialog 205 | - `[+]` fixes in man page 206 | - `[+]` build icon browser by default [0.42.60] 207 | 208 | Version 6.0 209 | 210 | - `[+]` add --use-interp option ⁽²⁾ [0.42.45] 211 | - `[+]` add link field to --form dialog [0.42.47] 212 | - `[-]` returning customizable options for --text-info dialog ⁽⁷⁾ [0.42.44] 213 | - `[+]` fix yad behavior outside X11 (special thanks to Michael Weiser) ⁽⁸⁾ [0.42.59] 214 | - `[?]` improve dialog window placement [8b0e5af] 215 | - `[+]` update translations 216 | 217 | Version 5.0 218 | 219 | - `[+]` add debug mode. this feature can be turned on through gsettings. ⁽⁵⁾ [0.42.55] 220 | - `[!]` add configure option --enable-standalone for build yad without gsettings support ⁽⁵⁾ 221 | - `[+]` fix expanding tree nodes for stdin data 222 | - `[+]` some fixes in print dialog [0.42.38] 223 | - `[+]` fix --uri-handler option in html dialog [0.42.46] 224 | - `[+]` fix wrong autoclose behavior in progress dialog [0.42.57] 225 | 226 | Version 4.1 227 | 228 | - `[+]` fix handling tree data from stdin in list dialog [0.42.35] 229 | 230 | Version 4.0 231 | 232 | - `[>]` font can be selected with double-click in font dialog 233 | - `[>]` add application chooser dialog and application chooser field in form dialog 234 | - `[+]` add tree mode in list dialog [0.42.33] -> [0.42.35] 235 | - `[+]` add --hide-text option to progress dialogs [0.42.31] 236 | - `[+]` multi-progress dialog features merged with progress dialog. Separate multi-progress dialog no longer exists ⁽⁶⁾ [0.42.42] 237 | - `[>]` enable markup in progress log window 238 | - `[+]` fix output of color values in hex notation [2e75f42] 239 | - `[+]` removed \*-selection aliases for --file, --color and --font dialogs ⁽³⁾ 240 | 241 | Version 3.0 242 | 243 | - `[+]` add user defined handlers for all editing actions in list dialog. 244 | 245 | - `[!]` fix loading text from file in text-info dialog 246 | - `[!]` fix gsettings key names 247 | 248 | Version 2.0 249 | 250 | - `[!]` migrate to gsettings from config file ⁽⁵⁾ 251 | - `[+]` add --keep-icon-size option [0.42.26] 252 | - `[+]` icon browser shows only non-symbolic icons by default [0.42.66] ⁽¹⁰⁾ 253 | - `[>]` fix segfault in text-info dialog when empty file is specified ⁽⁴⁾ 254 | - `[+]` fix initial selection in selectable labels 255 | 256 | Version 1.0 257 | 258 | - `[-]` completely removed support of gtk+-2.0 259 | - `[+]` minimum required gtk+ version bump to 3.22.0 260 | - `[>]` add --formatted option to text-info dialog for displaing text with pango markup 261 | - `[+]` add --expand option to tab dialog 262 | - `[+]` default protocol for html widget is https now 263 | - `[-]` gtk stock items not used anymore. instead there are some yad predefined names. details can be found in man page 264 | - `[+]` add --bool-fmt for different forms of boolean values output. all of this forms recognized on input automatically 265 | - `[!]` gspell library now used for spell checking 266 | - `[+]` tray icon is optional now. this dialog is enabled by default but can be turned off with ./configure --disable-tray [0.42.58] 267 | - `[-]` remove --fore, --back and --font options for text-info dialog. those functionality can be done through custom css 268 | 269 | Version 0.42.0 270 | 271 | - `[+]` add pfd utility for fontnames transformation in scripts 272 | - `[+]` add 'menu' action for notification icon 273 | - `[+]` add --icon-size option to icon dialog 274 | - `[+]` add --simple-tips option to list dialog 275 | - `[+]` fixes in setting window size 276 | - `[+]` improve size scaling in separate output of font dialog 277 | 278 | See the NEWS file for older versions. 279 | 280 | ## Notes 281 | 282 | (§)N Refer our pull request (PR) number N [https://github.com/v1cont/yad/pulls?q=author%3Astep-](https://github.com/v1cont/yad/pulls?q=author%3Astep-) 283 | 284 | ⁽¹⁾ The GTK+-2 package in your distribution may need a patch to fix a long-standing issue whereby the GTK+ "Print to File" printer silently fails to print. This bug affects other GTK+-2 applications, such as evince, and does not involve CUPS printers. See this [commit message](https://github.com/step-/yad/commit/c3322e79). 285 | 286 | ⁽²⁾ Use interpreter option `--use-interp`. yadL default interpreter is `sh -c '%'` whereas it is `bash -c '%'` for yadU. 287 | 288 | ⁽³⁾ yadU commit removed undocumented aliases for `--color`, `--file` and `--font options`; Fatdog64's scripts did not use the removed options; yadL commit fd5dea9. 289 | 290 | ⁽⁴⁾ Not applicable. 291 | 292 | ⁽⁵⁾ yadL saves print settings to new file `$XDG_CONFIG_HOME/yad/print.conf`, and other settings to `$XDG_CONFIG_HOME/yad.conf`. Instead, yadU uses `gsettings` to save its configuration; it can be built "standalone" without `gsettings` but then there is no `yad.conf` to save the configuration. 293 | 294 | ⁽⁶⁾ yadL still provides option `--multi-progress` as a deprecated alias for `--progress`. 295 | 296 | ⁽⁷⁾ yadU changed the `--fontname` format of text dialog from Pango style to CSS style [fe11080]+[4b54d14] then back to Pango style [244919d]. yadL has always used Pango style [3858704]. 297 | 298 | ⁽⁸⁾ GTK+-2 does not provide a GDK Wayland backend. yadU and yadL equally support Wayland for GTK+-3 builds but some dialog features may not be available. If configuration option `debug` is enabled, yadL and yadU will print a warning when an unavailable feature is requested. To run yadL/yadU in this way, select the Wayland backend by setting `GDK_BACKEND=wayland,x11` in the application's environment. Special value `GDK_BACKEND=help` displays the available backends. 299 | 300 | ⁽⁹⁾ GTK+-2 generates the preview image when a file item is selected interactively. Therefore `yad --file --filename=/my/pic.jpg --file --preview [--large-preview]` will not start with the preview of pic.jpg loaded. 301 | 302 | ⁽¹⁰⁾ GTK+-2 cannot discriminate symbolic icons. Therefore yad icon browser options `--all` and `--symbolic` are ignored. 303 | 304 | ⁽¹¹⁾ GTK+-2 `yad-tools --icon --size` always prints the scalable icon name, if available, regardless of the requested size; a similar remark applies to options `--icon --type`. 305 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('yad', 'c', version: '0.42.81', license: 'GPLv3') 2 | 3 | subdir('po') 4 | subdir('src') 5 | subdir('data') 6 | -------------------------------------------------------------------------------- /meson_options.txt: -------------------------------------------------------------------------------- 1 | option('rgb', type: 'string', value: '/etc/X11/rgb.txt', description: 'Set path to rgb.txt file') 2 | -------------------------------------------------------------------------------- /po/LINGUAS: -------------------------------------------------------------------------------- 1 | # yad translations 2 | # 3 | # please keep this list sorted alphabetically 4 | # 5 | de 6 | es 7 | fr 8 | it 9 | pt_BR 10 | ru 11 | sk 12 | uk 13 | zh_TW 14 | -------------------------------------------------------------------------------- /po/POTFILES.in: -------------------------------------------------------------------------------- 1 | src/about.c 2 | src/calendar.c 3 | src/entry.c 4 | src/file.c 5 | src/font.c 6 | src/form.c 7 | src/html.c 8 | src/icons.c 9 | src/main.c 10 | src/notification.c 11 | src/scale.c 12 | src/list.c 13 | src/option.c 14 | src/multi-progress.c 15 | src/paned.c 16 | src/picture.c 17 | src/print.c 18 | src/progress.c 19 | src/color.c 20 | src/text.c 21 | src/browser.c 22 | src/notebook.c 23 | src/tools.c 24 | data/yad-icon-browser.desktop.in 25 | -------------------------------------------------------------------------------- /po/meson.build: -------------------------------------------------------------------------------- 1 | i18n = import('i18n') 2 | add_project_arguments('-DGETTEXT_PACKAGE="yad"', language:'c') 3 | i18n.gettext('yad') 4 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | AM_CPPFLAGS = \ 2 | -DLOCALEDIR=\""$(datadir)/locale"\" \ 3 | @DISABLE_DEPRECATED@ 4 | 5 | bin_PROGRAMS = yad 6 | 7 | if GTK2 8 | CPICKER_SOURCES = cpicker_gtk2.c cpicker.h 9 | else 10 | CPICKER_SOURCES = cpicker.c cpicker.h 11 | endif 12 | 13 | yad_SOURCES = \ 14 | about.c \ 15 | calendar.c \ 16 | color.c \ 17 | dnd.c \ 18 | entry.c \ 19 | file.c \ 20 | font.c \ 21 | form.c \ 22 | icons.c \ 23 | list.c \ 24 | notebook.c \ 25 | option.c \ 26 | paned.c \ 27 | picture.c \ 28 | print.c \ 29 | progress.c \ 30 | scale.c \ 31 | text.c \ 32 | util.c \ 33 | main.c \ 34 | yad.h \ 35 | calendar.xpm \ 36 | $(CPICKER_SOURCES) 37 | 38 | if TRAY 39 | yad_SOURCES += notification.c 40 | endif 41 | 42 | if HTML 43 | yad_SOURCES += html.c 44 | endif 45 | 46 | yad_CFLAGS = $(GTK_CFLAGS) $(HTML_CFLAGS) $(SPELL_CFLAGS) $(SOURCEVIEW_CFLAGS) 47 | yad_LDADD = $(GTK_LIBS) $(HTML_LIBS) $(SPELL_LIBS) $(SOURCEVIEW_LIBS) 48 | 49 | if BUILD_TOOLS 50 | bin_PROGRAMS += yad-tools 51 | 52 | yad_tools_SOURCES = tools.c $(CPICKER_SOURCES) 53 | yad_tools_CFLAGS = $(GTK_CFLAGS) $(SPELL_CFLAGS) $(SOURCEVIEW_CFLAGS) 54 | yad_tools_LDADD = $(GTK_LIBS) $(SPELL_LIBS) $(SOURCEVIEW_LIBS) 55 | endif 56 | 57 | if BUILD_IB 58 | bin_PROGRAMS += yad-icon-browser 59 | 60 | yad_icon_browser_SOURCES = browser.c 61 | yad_icon_browser_CFLAGS = $(GTK_CFLAGS) 62 | yad_icon_browser_LDADD = $(GTK_LIBS) 63 | endif 64 | -------------------------------------------------------------------------------- /src/about.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of YAD. 3 | * 4 | * YAD 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 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * YAD is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with YAD. If not, see . 16 | * 17 | * Copyright (C) 2008-2019, Victor Ananjevsky 18 | */ 19 | 20 | #include "yad.h" 21 | 22 | gint 23 | yad_about (void) 24 | { 25 | GtkWidget *dialog; 26 | const gchar *const authors_et_al[] = { 27 | "Victor Ananjevsky ", 28 | PACKAGE_URL " ", 29 | "step http://github.com/step-/yad/" " ", 30 | NULL 31 | }; 32 | gchar * roles[] = { 33 | _("Author:\n\t%s"), 34 | _("Homepage:\n\t%s"), 35 | _("Maintainer GTK+ 2:\n\t%s"), 36 | NULL 37 | }; 38 | const gchar *translators = N_("translator-credits"); 39 | const gchar *license = 40 | N_("YAD is free software; you can redistribute it and/or modify " 41 | "it under the terms of the GNU General Public License as published by " 42 | "the Free Software Foundation; either version 3 of the License, or " 43 | "(at your option) any later version.\n\n" 44 | "YAD is distributed in the hope that it will be useful, " 45 | "but WITHOUT ANY WARRANTY; without even the implied warranty of " 46 | "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the " 47 | "GNU General Public License for more details.\n\n" 48 | "You should have received a copy of the GNU General Public License " 49 | "along with YAD. If not, see http://www.gnu.org/licenses/\x20."); 50 | 51 | gchar **p, **q; 52 | for (p = (gchar **) authors_et_al, q = roles; *p && *q; p++, q++) 53 | *q = g_strdup_printf (*q, *p); 54 | 55 | gchar *comments = g_strdup_printf (_("Yet Another Dialog\n" 56 | "(show dialog boxes from shell scripts)\n" 57 | "\nBased on Zenity code\n\n" 58 | #ifdef HAVE_HTML 59 | "Built with Webkit\n" 60 | #endif 61 | #ifdef HAVE_SOURCEVIEW 62 | "Built with GtkSourceView\n" 63 | #endif 64 | #ifdef HAVE_SPELL 65 | "Built with GtkSpell\n" 66 | #endif 67 | "Using GTK+ %d.%d.%d\n\n" 68 | "CLICK CREDITS FOR LINKS\n"), 69 | gtk_major_version, gtk_minor_version, gtk_micro_version); 70 | 71 | dialog = gtk_about_dialog_new (); 72 | gtk_window_set_icon_name (GTK_WINDOW (dialog), "yad"); 73 | g_object_set (G_OBJECT (dialog), 74 | "name", PACKAGE_NAME, 75 | "version", PACKAGE_VERSION, 76 | "copyright", "Copyright \xc2\xa9 2008-2019, Victor Ananjevsky\n" 77 | "Copyright \xc2\xa9 2019-2023, step", 78 | "comments", comments, 79 | "authors", roles, 80 | "website", "", 81 | "translator-credits", translators, 82 | "wrap-license", TRUE, 83 | "license", license, 84 | "logo-icon-name", "yad", 85 | NULL); 86 | 87 | return gtk_dialog_run (GTK_DIALOG (dialog)); 88 | } 89 | -------------------------------------------------------------------------------- /src/browser.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of YAD. 3 | * 4 | * YAD 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 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * YAD is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with YAD. If not, see . 16 | * 17 | * Copyright (C) 2010-2019, Victor Ananjevsky 18 | */ 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | typedef struct { 27 | GtkWidget *win; 28 | GtkWidget *image; 29 | GtkWidget *lname; 30 | GtkWidget *lsize; 31 | GtkWidget *lfile; 32 | GtkWidget *cat_list; 33 | GtkWidget *icon_list; 34 | 35 | GtkIconTheme *theme; 36 | 37 | GHashTable *icons; 38 | } IconBrowserData; 39 | 40 | static gboolean show_regular = TRUE; 41 | static gboolean show_symbolic = FALSE; 42 | 43 | static gboolean 44 | key_press_cb (GtkWidget * w, GdkEventKey * ev, gpointer data) 45 | { 46 | if (ev->keyval == GDK_KEY_Escape) 47 | { 48 | gtk_main_quit (); 49 | return TRUE; 50 | } 51 | return FALSE; 52 | } 53 | 54 | static GtkListStore * 55 | load_icon_cat (IconBrowserData * data, gchar * cat) 56 | { 57 | GtkListStore *store; 58 | GList *i, *icons; 59 | gint size, w, h; 60 | 61 | gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &w, &h); 62 | size = MIN (w, h); 63 | 64 | store = gtk_list_store_new (2, GDK_TYPE_PIXBUF, G_TYPE_STRING); 65 | 66 | icons = gtk_icon_theme_list_icons (data->theme, cat); 67 | for (i = icons; i; i = i->next) 68 | { 69 | GtkTreeIter iter; 70 | GdkPixbuf *pb, *spb; 71 | #if GTK_CHECK_VERSION(3,0,0) 72 | GtkIconInfo *info; 73 | 74 | info = gtk_icon_theme_lookup_icon (data->theme, i->data, size, 0); 75 | if (gtk_icon_info_is_symbolic (info)) 76 | { 77 | if (!show_symbolic) 78 | continue; 79 | } 80 | else 81 | { 82 | if (!show_regular) 83 | continue; 84 | } 85 | g_object_unref (info); 86 | 87 | spb = pb = gtk_icon_theme_load_icon (data->theme, i->data, size, 0, NULL); 88 | #else 89 | /* GTK+-2 can't discriminate symbolic icons */ 90 | spb = pb = gtk_icon_theme_load_icon (data->theme, i->data, size, GTK_ICON_LOOKUP_GENERIC_FALLBACK, NULL); 91 | #endif 92 | 93 | if (pb) 94 | { 95 | /* scale pixbuf if needed */ 96 | w = gdk_pixbuf_get_width (pb); 97 | h = gdk_pixbuf_get_height (pb); 98 | if (w > size || h > size) 99 | { 100 | pb = gdk_pixbuf_scale_simple (spb, size, size, GDK_INTERP_BILINEAR); 101 | g_object_unref (spb); 102 | } 103 | } 104 | 105 | gtk_list_store_append (store, &iter); 106 | gtk_list_store_set (store, &iter, 0, pb, 1, i->data, -1); 107 | 108 | if (pb) 109 | g_object_unref (pb); 110 | } 111 | g_list_free_full (icons, g_free); 112 | 113 | gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), 1, GTK_SORT_ASCENDING); 114 | 115 | return store; 116 | } 117 | 118 | static void 119 | print_icon (GtkTreeView *tv, GtkTreePath *path, GtkTreeViewColumn *col, IconBrowserData *data) 120 | { 121 | GtkTreeModel *model; 122 | GtkTreeIter iter; 123 | gchar *icon; 124 | 125 | model = gtk_tree_view_get_model (tv); 126 | gtk_tree_model_get_iter (model, &iter, path); 127 | gtk_tree_model_get (model, &iter, 1, &icon, -1); 128 | 129 | g_print ("%s\n", icon); 130 | 131 | gtk_main_quit (); 132 | } 133 | 134 | static void 135 | select_icon (GtkTreeSelection * sel, IconBrowserData * data) 136 | { 137 | GtkTreeModel *model; 138 | GtkTreeIter iter; 139 | GtkIconInfo *info; 140 | gint *sz, i; 141 | gchar *icon, *file; 142 | GString *sizes; 143 | 144 | if (!gtk_tree_selection_get_selected (sel, &model, &iter)) 145 | return; 146 | 147 | gtk_tree_model_get (model, &iter, 1, &icon, -1); 148 | 149 | gtk_image_set_from_icon_name (GTK_IMAGE (data->image), icon, GTK_ICON_SIZE_DIALOG); 150 | 151 | sz = gtk_icon_theme_get_icon_sizes (data->theme, icon); 152 | info = gtk_icon_theme_lookup_icon (data->theme, icon, sz[0], 0); 153 | 154 | if (info) 155 | file = (gchar *) gtk_icon_info_get_filename (info); 156 | else 157 | file = NULL; 158 | 159 | /* create sizes string */ 160 | i = 0; 161 | sizes = g_string_new (""); 162 | while (sz[i]) 163 | { 164 | if (sz[i] == -1) 165 | g_string_append (sizes, _("scalable ")); 166 | else 167 | g_string_append_printf (sizes, "%dx%d ", sz[i], sz[i]); 168 | i++; 169 | } 170 | /* free memory */ 171 | g_free (sz); 172 | 173 | gtk_label_set_text (GTK_LABEL (data->lname), icon); 174 | gtk_label_set_text (GTK_LABEL (data->lsize), sizes->str); 175 | gtk_label_set_text (GTK_LABEL (data->lfile), file ? file : _("built-in")); 176 | 177 | g_string_free (sizes, TRUE); 178 | 179 | if (info) 180 | #if !GTK_CHECK_VERSION(3,0,0) 181 | gtk_icon_info_free(info); 182 | #else 183 | g_object_unref (info); 184 | #endif 185 | } 186 | 187 | static void 188 | select_cat (GtkTreeSelection * sel, IconBrowserData * data) 189 | { 190 | GtkTreeModel *model; 191 | GtkListStore *store; 192 | GtkTreeIter iter; 193 | gchar *cat; 194 | 195 | if (!gtk_tree_selection_get_selected (sel, &model, &iter)) 196 | return; 197 | 198 | gtk_tree_model_get (model, &iter, 0, &cat, -1); 199 | 200 | store = g_hash_table_lookup (data->icons, cat); 201 | if (!store) 202 | { 203 | store = load_icon_cat (data, cat); 204 | g_hash_table_insert (data->icons, cat, store); 205 | } 206 | gtk_tree_view_set_model (GTK_TREE_VIEW (data->icon_list), GTK_TREE_MODEL (store)); 207 | } 208 | 209 | gint 210 | main (gint argc, gchar * argv[]) 211 | { 212 | IconBrowserData *data; 213 | gchar **themes = NULL; 214 | GList *ic, *icat; 215 | GtkListStore *store; 216 | GtkTreeSelection *sel; 217 | GtkTreeViewColumn *col; 218 | GtkCellRenderer *r; 219 | GtkWidget *w, *p, *box, *t; 220 | gboolean ver = FALSE; 221 | gboolean all = FALSE, symbolic = FALSE, interactive = FALSE; 222 | 223 | GError *err = NULL; 224 | GOptionContext *ctx; 225 | 226 | GOptionEntry entrs[] = { 227 | { "version", 'v', 0, G_OPTION_ARG_NONE, &ver, N_("Print version"), NULL }, 228 | { "all", 'a', 0, G_OPTION_ARG_NONE, &all, _("Show all icons"), NULL }, 229 | { "symbolic", 's', 0, G_OPTION_ARG_NONE, &symbolic, _("Show only symbolic icons"), NULL }, 230 | { "interactive", 'i', 0, G_OPTION_ARG_NONE, &interactive, _("Select and print icon on double-click"), NULL }, 231 | { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &themes, NULL, NULL }, 232 | { NULL } 233 | }; 234 | 235 | data = g_new0 (IconBrowserData, 1); 236 | 237 | #ifdef ENABLE_NLS 238 | bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); 239 | bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); 240 | textdomain (GETTEXT_PACKAGE); 241 | #endif 242 | 243 | /* Parse the command line arguments */ 244 | ctx = g_option_context_new (_("- Icon browser")); 245 | g_option_context_set_ignore_unknown_options (ctx, TRUE); 246 | g_option_context_add_main_entries (ctx, entrs, GETTEXT_PACKAGE); 247 | g_option_context_add_group (ctx, gtk_get_option_group (TRUE)); 248 | if (!g_option_context_parse (ctx, &argc, &argv, &err)) 249 | { 250 | g_printerr ("Option parsing failed: %s\n", err->message); 251 | return 1; 252 | } 253 | 254 | data = g_new0 (IconBrowserData, 1); 255 | 256 | if (ver) 257 | { 258 | g_print ("%s (GTK+ %d.%d.%d)\n", PACKAGE_VERSION, gtk_major_version, gtk_minor_version, gtk_micro_version); 259 | return 0; 260 | } 261 | 262 | if (all) 263 | { 264 | show_regular = TRUE; 265 | show_symbolic = TRUE; 266 | } 267 | else if (symbolic) 268 | { 269 | show_regular = FALSE; 270 | show_symbolic = TRUE; 271 | } 272 | 273 | /* load icon theme */ 274 | data->theme = gtk_icon_theme_get_default (); 275 | if (themes && themes[0]) 276 | { 277 | data->theme = gtk_icon_theme_new (); 278 | gtk_icon_theme_set_custom_theme (data->theme, themes[0]); 279 | } 280 | 281 | /* create interface */ 282 | data->win = gtk_window_new (GTK_WINDOW_TOPLEVEL); 283 | gtk_window_set_title (GTK_WINDOW (data->win), _("Icon browser")); 284 | gtk_window_set_icon_name (GTK_WINDOW (data->win), "gtk-info"); 285 | gtk_window_set_default_size (GTK_WINDOW (data->win), 500, 400); 286 | g_signal_connect (G_OBJECT (data->win), "delete-event", G_CALLBACK (gtk_main_quit), NULL); 287 | g_signal_connect (G_OBJECT (data->win), "key-press-event", G_CALLBACK (key_press_cb), NULL); 288 | 289 | #if !GTK_CHECK_VERSION(3,0,0) 290 | box = gtk_vbox_new (FALSE, 5); 291 | #else 292 | box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5); 293 | #endif 294 | gtk_container_add (GTK_CONTAINER (data->win), box); 295 | gtk_container_set_border_width (GTK_CONTAINER (data->win), 5); 296 | 297 | /* create icon info box */ 298 | #if !GTK_CHECK_VERSION(3,0,0) 299 | t = gtk_table_new (3, 3, FALSE); 300 | gtk_table_set_col_spacings (GTK_TABLE (t), 5); 301 | gtk_table_set_row_spacings (GTK_TABLE (t), 5); 302 | #else 303 | t = gtk_grid_new (); 304 | gtk_grid_set_row_spacing (GTK_GRID (t), 5); 305 | gtk_grid_set_column_spacing (GTK_GRID (t), 5); 306 | #endif 307 | gtk_box_pack_start (GTK_BOX (box), t, FALSE, FALSE, 2); 308 | 309 | data->image = gtk_image_new_from_icon_name ("image-missing", GTK_ICON_SIZE_DIALOG); 310 | #if !GTK_CHECK_VERSION(3,0,0) 311 | gtk_table_attach (GTK_TABLE (t), data->image, 0, 1, 0, 3, GTK_FILL, 0, 0, 0); 312 | #else 313 | gtk_grid_attach (GTK_GRID (t), data->image, 0, 0, 1, 3); 314 | #endif 315 | 316 | w = gtk_label_new (NULL); 317 | gtk_label_set_markup (GTK_LABEL (w), _("Name:")); 318 | #if !GTK_CHECK_VERSION(3,0,0) 319 | gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.5); 320 | gtk_table_attach (GTK_TABLE (t), w, 1, 2, 0, 1, GTK_FILL, 0, 0, 0); 321 | #else 322 | gtk_label_set_xalign (GTK_LABEL (w), 0.0); 323 | gtk_grid_attach (GTK_GRID (t), w, 1, 0, 1, 1); 324 | #endif 325 | data->lname = gtk_label_new (NULL); 326 | gtk_label_set_selectable (GTK_LABEL (data->lname), TRUE); 327 | #if !GTK_CHECK_VERSION(3,0,0) 328 | gtk_misc_set_alignment (GTK_MISC (data->lname), 0.0, 0.5); 329 | gtk_table_attach (GTK_TABLE (t), data->lname, 2, 3, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 0); 330 | #else 331 | gtk_label_set_xalign (GTK_LABEL (data->lname), 0.0); 332 | gtk_grid_attach (GTK_GRID (t), data->lname, 2, 0, 1, 1); 333 | gtk_widget_set_hexpand (data->lname, TRUE); 334 | #endif 335 | 336 | w = gtk_label_new (NULL); 337 | gtk_label_set_markup (GTK_LABEL (w), _("Sizes:")); 338 | #if !GTK_CHECK_VERSION(3,0,0) 339 | gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.5); 340 | gtk_table_attach (GTK_TABLE (t), w, 1, 2, 1, 2, GTK_FILL, 0, 0, 0); 341 | #else 342 | gtk_label_set_xalign (GTK_LABEL (w), 0.0); 343 | gtk_grid_attach (GTK_GRID (t), w, 1, 1, 1, 1); 344 | #endif 345 | data->lsize = gtk_label_new (NULL); 346 | gtk_label_set_selectable (GTK_LABEL (data->lsize), TRUE); 347 | #if !GTK_CHECK_VERSION(3,0,0) 348 | gtk_misc_set_alignment (GTK_MISC (data->lsize), 0.0, 0.5); 349 | gtk_table_attach (GTK_TABLE (t), data->lsize, 2, 3, 1, 2, GTK_FILL | GTK_EXPAND, 0, 0, 0); 350 | #else 351 | gtk_label_set_xalign (GTK_LABEL (data->lsize), 0.0); 352 | gtk_grid_attach (GTK_GRID (t), data->lsize, 2, 1, 1, 1); 353 | gtk_widget_set_hexpand (data->lsize, TRUE); 354 | #endif 355 | 356 | w = gtk_label_new (NULL); 357 | gtk_label_set_markup (GTK_LABEL (w), _("Filename:")); 358 | #if !GTK_CHECK_VERSION(3,0,0) 359 | gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.5); 360 | gtk_table_attach (GTK_TABLE (t), w, 1, 2, 2, 3, GTK_FILL, 0, 0, 0); 361 | #else 362 | gtk_label_set_xalign (GTK_LABEL (w), 0.0); 363 | gtk_grid_attach (GTK_GRID (t), w, 1, 2, 1, 1); 364 | #endif 365 | data->lfile = gtk_label_new (NULL); 366 | gtk_label_set_selectable (GTK_LABEL (data->lfile), TRUE); 367 | #if !GTK_CHECK_VERSION(3,0,0) 368 | gtk_misc_set_alignment (GTK_MISC (data->lfile), 0.0, 0.5); 369 | gtk_table_attach (GTK_TABLE (t), data->lfile, 2, 3, 2, 3, GTK_FILL | GTK_EXPAND, 0, 0, 0); 370 | #else 371 | gtk_label_set_xalign (GTK_LABEL (data->lfile), 0.0); 372 | gtk_grid_attach (GTK_GRID (t), data->lfile, 2, 2, 1, 1); 373 | gtk_widget_set_hexpand (data->lfile, TRUE); 374 | #endif 375 | 376 | /* create icon browser */ 377 | #if !GTK_CHECK_VERSION(3,0,0) 378 | p = gtk_hpaned_new (); 379 | #else 380 | p = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL); 381 | #endif 382 | gtk_paned_set_position (GTK_PANED (p), 150); 383 | gtk_box_pack_start (GTK_BOX (box), p, TRUE, TRUE, 2); 384 | 385 | /* create category list */ 386 | w = gtk_scrolled_window_new (NULL, NULL); 387 | gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (w), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); 388 | gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (w), GTK_SHADOW_ETCHED_IN); 389 | gtk_paned_add1 (GTK_PANED (p), w); 390 | 391 | store = gtk_list_store_new (1, G_TYPE_STRING); 392 | 393 | data->cat_list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store)); 394 | gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (data->cat_list), TRUE); 395 | gtk_container_add (GTK_CONTAINER (w), data->cat_list); 396 | 397 | sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (data->cat_list)); 398 | g_signal_connect (G_OBJECT (sel), "changed", G_CALLBACK (select_cat), data); 399 | 400 | r = gtk_cell_renderer_text_new (); 401 | col = gtk_tree_view_column_new_with_attributes (_("Category"), r, "text", 0, NULL); 402 | gtk_tree_view_column_set_expand (col, TRUE); 403 | gtk_tree_view_append_column (GTK_TREE_VIEW (data->cat_list), col); 404 | 405 | /* load icons category */ 406 | data->icons = g_hash_table_new (g_direct_hash, g_direct_equal); 407 | icat = gtk_icon_theme_list_contexts (data->theme); 408 | for (ic = icat; ic; ic = ic->next) 409 | { 410 | GtkTreeIter iter; 411 | 412 | gtk_list_store_append (store, &iter); 413 | gtk_list_store_set (store, &iter, 0, ic->data, -1); 414 | g_free (ic->data); 415 | } 416 | g_list_free (icat); 417 | 418 | /* create icons list */ 419 | w = gtk_scrolled_window_new (NULL, NULL); 420 | gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (w), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); 421 | gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (w), GTK_SHADOW_ETCHED_IN); 422 | gtk_paned_add2 (GTK_PANED (p), w); 423 | 424 | data->icon_list = gtk_tree_view_new (); 425 | gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (data->icon_list), TRUE); 426 | #if !GTK_CHECK_VERSION(3,0,0) 427 | gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (data->icon_list), TRUE); 428 | #endif 429 | gtk_container_add (GTK_CONTAINER (w), data->icon_list); 430 | 431 | sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (data->icon_list)); 432 | g_signal_connect (G_OBJECT (sel), "changed", G_CALLBACK (select_icon), data); 433 | 434 | if (interactive) 435 | g_signal_connect (G_OBJECT (data->icon_list), "row-activated", G_CALLBACK (print_icon), data); 436 | 437 | col = gtk_tree_view_column_new (); 438 | gtk_tree_view_column_set_title (col, _("Icons")); 439 | gtk_tree_view_column_set_sort_column_id (col, 1); 440 | r = gtk_cell_renderer_pixbuf_new (); 441 | gtk_tree_view_column_pack_start (col, r, FALSE); 442 | gtk_tree_view_column_set_attributes (col, r, "pixbuf", 0, NULL); 443 | r = gtk_cell_renderer_text_new (); 444 | gtk_tree_view_column_pack_start (col, r, FALSE); 445 | gtk_tree_view_column_set_attributes (col, r, "text", 1, NULL); 446 | gtk_tree_view_column_set_expand (col, TRUE); 447 | gtk_tree_view_append_column (GTK_TREE_VIEW (data->icon_list), col); 448 | 449 | gtk_widget_show_all (data->win); 450 | 451 | /* run it */ 452 | gtk_main (); 453 | 454 | return 0; 455 | } 456 | -------------------------------------------------------------------------------- /src/calendar.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of YAD. 3 | * 4 | * YAD 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 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * YAD is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with YAD. If not, see . 16 | * 17 | * Copyright (C) 2008-2019, Victor Ananjevsky 18 | */ 19 | 20 | #include 21 | 22 | #include "yad.h" 23 | 24 | static GtkWidget *calendar; 25 | 26 | static GHashTable *details; 27 | 28 | static void 29 | parse_details () 30 | { 31 | FILE *f; 32 | 33 | details = g_hash_table_new (g_str_hash, g_str_equal); 34 | 35 | /* open details file */ 36 | f = fopen (options.calendar_data.details, "r"); 37 | if (f == NULL) 38 | { 39 | g_printerr (_("Cannot open file '%s': %s\n"), options.common_data.uri, g_strerror (errno)); 40 | return; 41 | } 42 | 43 | /* read details file */ 44 | while (!feof (f)) 45 | { 46 | gchar buf[4096], **dtl; 47 | 48 | /* read string */ 49 | memset (buf, 0, 4096); 50 | fgets (buf, 4096, f); 51 | if (strlen (buf) > 0) 52 | { 53 | dtl = g_strsplit (buf, " ", 2); 54 | g_hash_table_insert (details, dtl[0], dtl[1]); 55 | } 56 | } 57 | 58 | fclose (f); 59 | } 60 | 61 | static gchar * 62 | get_details (GtkCalendar * cal, guint year, guint month, guint day, gpointer data) 63 | { 64 | GDate *d; 65 | gchar time_string[128]; 66 | gchar *str = NULL; 67 | 68 | d = g_date_new_dmy (day, month + 1, year); 69 | if (g_date_valid (d)) 70 | { 71 | g_date_strftime (time_string, 127, options.common_data.date_format, d); 72 | str = (gchar *) g_hash_table_lookup (details, time_string); 73 | } 74 | g_date_free (d); 75 | 76 | if (str) 77 | return g_strdup (str); 78 | return str; 79 | } 80 | 81 | static void 82 | double_click_cb (GtkWidget * w, gpointer data) 83 | { 84 | if (options.plug == -1) 85 | yad_exit (options.data.def_resp); 86 | } 87 | 88 | GtkWidget * 89 | calendar_create_widget (GtkWidget * dlg) 90 | { 91 | GtkWidget *w; 92 | gint cal_opts; 93 | 94 | w = calendar = gtk_calendar_new (); 95 | gtk_widget_set_name (w, "yad-calendar-widget"); 96 | 97 | if (options.calendar_data.month > 0 || options.calendar_data.year > 0) 98 | gtk_calendar_select_month (GTK_CALENDAR (w), options.calendar_data.month - 1, options.calendar_data.year); 99 | if (options.calendar_data.day > 0) 100 | gtk_calendar_select_day (GTK_CALENDAR (w), options.calendar_data.day); 101 | 102 | if (options.calendar_data.details) 103 | { 104 | parse_details (); 105 | gtk_calendar_set_detail_func (GTK_CALENDAR (w), get_details, NULL, NULL); 106 | } 107 | 108 | cal_opts = GTK_CALENDAR_SHOW_HEADING | GTK_CALENDAR_SHOW_DAY_NAMES; 109 | if (options.calendar_data.weeks) 110 | cal_opts |= GTK_CALENDAR_SHOW_WEEK_NUMBERS; 111 | gtk_calendar_set_display_options (GTK_CALENDAR (w), cal_opts); 112 | 113 | g_signal_connect (w, "day-selected-double-click", G_CALLBACK (double_click_cb), dlg); 114 | 115 | return w; 116 | } 117 | 118 | void 119 | calendar_print_result (void) 120 | { 121 | guint day, month, year; 122 | gchar time_string[128]; 123 | GDate *date = NULL; 124 | 125 | gtk_calendar_get_date (GTK_CALENDAR (calendar), &year, &month, &day); 126 | date = g_date_new_dmy (day, month + 1, year); 127 | g_date_strftime (time_string, 127, options.common_data.date_format, date); 128 | g_print ("%s\n", time_string); 129 | } 130 | -------------------------------------------------------------------------------- /src/calendar.xpm: -------------------------------------------------------------------------------- 1 | /* XPM */ 2 | static const char * calendar_xpm[] = { 3 | "16 16 79 1", 4 | " c None", 5 | ". c #898D88", 6 | "+ c #898B86", 7 | "@ c #8B8D89", 8 | "# c #945D04", 9 | "$ c #8F5A02", 10 | "% c #8E5902", 11 | "& c #878984", 12 | "* c #BFC0BB", 13 | "= c #D8D9D7", 14 | "- c #945D05", 15 | "; c #D9AC65", 16 | "> c #DEB36F", 17 | ", c #A5A7A3", 18 | "' c #E6E8E5", 19 | ") c #A9AAA7", 20 | "! c #DFB370", 21 | "~ c #DFB470", 22 | "{ c #F8F8F8", 23 | "] c #E0B571", 24 | "^ c #DCB069", 25 | "/ c #555753", 26 | "( c #D3D5D2", 27 | "_ c #989A95", 28 | ": c #D4D6D3", 29 | "< c #E0B671", 30 | "[ c #DEB26E", 31 | "} c #FFFFFF", 32 | "| c #C1C2BF", 33 | "1 c #91938F", 34 | "2 c #C2C3C0", 35 | "3 c #E1B671", 36 | "4 c #F5F5F5", 37 | "5 c #FDFDFD", 38 | "6 c #E6E6E6", 39 | "7 c #DEB26D", 40 | "8 c #808080", 41 | "9 c #686868", 42 | "0 c #5C5C5C", 43 | "a c #989898", 44 | "b c #DEB26C", 45 | "c c #CFCFCF", 46 | "d c #3F3F3F", 47 | "e c #E2B671", 48 | "f c #DFB36C", 49 | "g c #6A6A6A", 50 | "h c #282828", 51 | "i c #A1A1A1", 52 | "j c #E2B570", 53 | "k c #E0E0E0", 54 | "l c #2B2B2B", 55 | "m c #959691", 56 | "n c #888A85", 57 | "o c #646661", 58 | "p c #E2B670", 59 | "q c #616161", 60 | "r c #656565", 61 | "s c #636363", 62 | "t c #8F8F8F", 63 | "u c #EEEEED", 64 | "v c #979893", 65 | "w c #646662", 66 | "x c #E3B670", 67 | "y c #D3D7CF", 68 | "z c #DFB26B", 69 | "A c #E4B76F", 70 | "B c #DBAD64", 71 | "C c #E0B36B", 72 | "D c #E1B46C", 73 | "E c #E1B36C", 74 | "F c #E1B46D", 75 | "G c #E2B56D", 76 | "H c #E2B46D", 77 | "I c #E2B66E", 78 | "J c #E3B56F", 79 | "K c #E3B66F", 80 | "L c #E4B66F", 81 | "M c #DFB169", 82 | "N c #945F05", 83 | " .+@ .+@ ", 84 | "#$%%&*&%%&=&%%$-", 85 | "$;>>,')!~,{)]]^$", 86 | "%>//&(_//&:_//<%", 87 | "%[/}|12}}|1|}/3%", 88 | "%[/}45466454}/3%", 89 | "%7/}66890a66}/3%", 90 | "%b/}6666cd66}/e%", 91 | "%f/}666ghi66}/j%", 92 | "%f/}6666kl6mnop%", 93 | "%f/}66qrst6&u/p%", 94 | "%f/}}}}}}}}vnwx%", 95 | "%f/yyyyyyyyyy/x%", 96 | "%z////////////A%", 97 | "$BCDEFFGHGIJKLM$", 98 | "-$%%%%%%%%%%%%$N"}; 99 | -------------------------------------------------------------------------------- /src/color.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of YAD. 3 | * 4 | * YAD 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 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * YAD is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with YAD. If not, see . 16 | * 17 | * Copyright (C) 2008-2019, Victor Ananjevsky 18 | */ 19 | 20 | #include 21 | 22 | #include "yad.h" 23 | #if GTK_CHECK_VERSION(3,0,0) 24 | #include "cpicker.h" 25 | #endif 26 | 27 | static GtkWidget *color; 28 | 29 | static GtkTreeModel * 30 | create_palette () 31 | { 32 | FILE *fp; 33 | gchar *filename; 34 | gchar buf[1024], *name; 35 | GtkListStore *store; 36 | GdkPixbuf *pb; 37 | GtkTreeIter iter; 38 | 39 | gchar *cxpm[] = { 40 | "16 14 1 1", 41 | ". c #FFFFFF", 42 | "................", 43 | "................", 44 | "................", 45 | "................", 46 | "................", 47 | "................", 48 | "................", 49 | "................", 50 | "................", 51 | "................", 52 | "................", 53 | "................", 54 | "................", 55 | "................" 56 | }; 57 | gchar cl[] = ". c #FFFFFF"; 58 | 59 | if (options.color_data.palette) 60 | filename = options.color_data.palette; 61 | else 62 | filename = RGB_FILE; 63 | 64 | if ((fp = fopen (filename, "r")) == NULL) 65 | { 66 | g_printerr (_("Can't open file %s: %s\n"), filename, strerror (errno)); 67 | return NULL; 68 | } 69 | 70 | store = gtk_list_store_new (3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING); 71 | 72 | while ((name = fgets (buf, sizeof (buf), fp)) != NULL) 73 | { 74 | gint r, g, b; 75 | gchar spec[8]; 76 | 77 | if (buf[0] == '!') 78 | continue; 79 | 80 | sscanf (buf, "%d %d %d", &r, &g, &b); 81 | 82 | g_sprintf (spec, "#%.2X%.2X%.2X", r, g, b); 83 | g_sprintf (cl, ". c #%.2X%.2X%.2X", r, g, b); 84 | cxpm[1] = cl; 85 | pb = gdk_pixbuf_new_from_xpm_data ((const gchar **) cxpm); 86 | 87 | while (g_ascii_isdigit (*name) || g_ascii_isspace (*name)) 88 | name++; 89 | 90 | gtk_list_store_append (store, &iter); 91 | gtk_list_store_set (store, &iter, 0, pb, 1, spec, 2, g_strstrip (name), -1); 92 | } 93 | 94 | fclose (fp); 95 | 96 | return GTK_TREE_MODEL (store); 97 | } 98 | 99 | static void 100 | set_color (gchar *clr) 101 | { 102 | #if !GTK_CHECK_VERSION(3,4,0) 103 | GdkColor c; 104 | if (gdk_color_parse (clr, &c)) 105 | gtk_color_selection_set_current_color (GTK_COLOR_SELECTION (color), &c); 106 | #else 107 | GdkRGBA c; 108 | if (gdk_rgba_parse (&c, clr)) 109 | gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (color), &c); 110 | #endif 111 | } 112 | 113 | #if GTK_CHECK_VERSION(3,0,0) 114 | static void 115 | picker_clicked (GtkWidget *w, gpointer data) 116 | { 117 | yad_get_screen_color (color); 118 | } 119 | #endif 120 | 121 | static void 122 | palette_changed (GtkTreeSelection * sel, gpointer data) 123 | { 124 | GtkTreeModel *model; 125 | GtkTreeIter iter; 126 | 127 | if (gtk_tree_selection_get_selected (sel, &model, &iter)) 128 | { 129 | gchar *clr; 130 | gtk_tree_model_get (model, &iter, 1, &clr, -1); 131 | set_color (clr); 132 | } 133 | } 134 | 135 | GtkWidget * 136 | color_create_widget (GtkWidget * dlg) 137 | { 138 | GtkWidget *w; 139 | 140 | #if !GTK_CHECK_VERSION(3,4,0) 141 | w = gtk_vbox_new (FALSE, 2); 142 | color = gtk_color_selection_new (); 143 | #else 144 | w = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2); 145 | color = gtk_color_chooser_widget_new (); 146 | #endif 147 | 148 | gtk_widget_set_name (color, "yad-color-widget"); 149 | #if !GTK_CHECK_VERSION(3,4,0) 150 | gtk_color_selection_set_has_palette (GTK_COLOR_SELECTION (color), options.color_data.gtk_palette); 151 | #else 152 | g_object_set (G_OBJECT (color), "show-editor", !options.color_data.gtk_palette, NULL); 153 | #endif 154 | if (options.color_data.init_color) 155 | set_color (options.color_data.init_color); 156 | gtk_box_pack_start (GTK_BOX (w), color, FALSE, FALSE, 2); 157 | 158 | #if GTK_CHECK_VERSION(3,0,0) 159 | if (options.color_data.color_picker) 160 | { 161 | GtkWidget *b, *i; 162 | 163 | b = gtk_button_new_with_label (_("Pick screen color")); 164 | 165 | i = gtk_image_new_from_icon_name ("gtk-color-picker", GTK_ICON_SIZE_BUTTON); 166 | gtk_button_set_image (GTK_BUTTON (b), i); 167 | g_object_set (G_OBJECT (b), "always-show-image", TRUE, NULL); 168 | 169 | g_signal_connect (G_OBJECT (b), "clicked", G_CALLBACK (picker_clicked), NULL); 170 | 171 | gtk_box_pack_start (GTK_BOX (w), b, FALSE, FALSE, 2); 172 | } 173 | #endif 174 | 175 | if (options.color_data.use_palette) 176 | { 177 | GtkTreeModel *model; 178 | 179 | if ((model = create_palette ()) != NULL) 180 | { 181 | GtkWidget *exp, *sw, *list; 182 | GtkCellRenderer *r; 183 | GtkTreeViewColumn *col; 184 | GtkTreeSelection *sel; 185 | 186 | /* create expander */ 187 | exp = gtk_expander_new (_("Palette")); 188 | gtk_expander_set_expanded (GTK_EXPANDER (exp), options.color_data.expand_palette); 189 | gtk_container_set_border_width (GTK_CONTAINER (exp), 5); 190 | gtk_box_pack_start (GTK_BOX (w), exp, TRUE, TRUE, 2); 191 | 192 | /* create color list */ 193 | sw = gtk_scrolled_window_new (NULL, NULL); 194 | gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN); 195 | gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), options.hscroll_policy, options.vscroll_policy); 196 | gtk_widget_set_size_request (sw, -1, 75); 197 | gtk_container_add (GTK_CONTAINER (exp), sw); 198 | #if GTK_CHECK_VERSION(3,0,0) 199 | gtk_widget_set_vexpand (sw, TRUE); 200 | #endif 201 | list = gtk_tree_view_new_with_model (model); 202 | gtk_widget_set_name (list, "yad-color-palette"); 203 | g_object_unref (model); 204 | gtk_container_add (GTK_CONTAINER (sw), list); 205 | 206 | /* add first columns */ 207 | col = gtk_tree_view_column_new (); 208 | gtk_tree_view_column_set_title (col, _("Color")); 209 | 210 | /* pixbuf */ 211 | r = gtk_cell_renderer_pixbuf_new (); 212 | gtk_tree_view_column_pack_start (col, r, FALSE); 213 | gtk_tree_view_column_set_attributes (col, r, "pixbuf", 0, NULL); 214 | 215 | /* color value */ 216 | r = gtk_cell_renderer_text_new (); 217 | gtk_tree_view_column_pack_start (col, r, TRUE); 218 | gtk_tree_view_column_set_attributes (col, r, "text", 1, NULL); 219 | 220 | gtk_tree_view_column_set_sort_column_id (col, 1); 221 | gtk_tree_view_append_column (GTK_TREE_VIEW (list), col); 222 | 223 | /* add second column */ 224 | r = gtk_cell_renderer_text_new (); 225 | col = gtk_tree_view_column_new_with_attributes (_("Name"), r, "text", 2, NULL); 226 | gtk_tree_view_column_set_sort_column_id (col, 2); 227 | gtk_tree_view_append_column (GTK_TREE_VIEW (list), col); 228 | 229 | /* enable searching on Name column */ 230 | gtk_tree_view_set_search_column (GTK_TREE_VIEW (list), 2); 231 | 232 | /* setup the selection handler */ 233 | sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (list)); 234 | gtk_tree_selection_set_mode (sel, GTK_SELECTION_SINGLE); 235 | g_signal_connect (G_OBJECT (sel), "changed", G_CALLBACK (palette_changed), NULL); 236 | 237 | gtk_widget_show_all (exp); 238 | } 239 | } 240 | 241 | return w; 242 | } 243 | 244 | void 245 | color_print_result (void) 246 | { 247 | #if !GTK_CHECK_VERSION(3,4,0) 248 | GdkColor c; 249 | guint64 alpha; 250 | #else 251 | GdkRGBA c; 252 | #endif 253 | gchar *cs; 254 | 255 | #if !GTK_CHECK_VERSION(3,4,0) 256 | gtk_color_selection_get_current_color (GTK_COLOR_SELECTION (color), &c); 257 | alpha = gtk_color_selection_get_current_alpha (GTK_COLOR_SELECTION (color)); 258 | cs = get_color (&c, alpha); 259 | #else 260 | gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (color), &c); 261 | cs = get_color (&c); 262 | #endif 263 | 264 | if (cs) 265 | g_printf ("%s\n", cs); 266 | } 267 | -------------------------------------------------------------------------------- /src/cpicker.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * This file is part of YAD. 4 | * 5 | * YAD is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * YAD is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with YAD. If not, see . 17 | * 18 | * Copyright (C) 2020-2022, Victor Ananjevsky 19 | */ 20 | 21 | /* This code getted from deprecated GtkColorSelection widget (gtk+-3.24.33) */ 22 | 23 | #define GDK_DISABLE_DEPRECATION_WARNINGS 24 | 25 | #include "cpicker.h" 26 | 27 | #define BIG_STEP 20 28 | 29 | typedef struct { 30 | GtkWidget *color_widget; 31 | GtkWidget *grab_widget; 32 | GdkDevice *keyb_device; 33 | GdkDevice *pointer_device; 34 | gboolean has_grab; 35 | guint32 time; 36 | } GrabData; 37 | 38 | static GdkRGBA selected_color; /* selected color */ 39 | static gboolean pickup_made = FALSE; /* true when color was picked up */ 40 | static gboolean pickup_done = FALSE; /* true when pickup was made or canceled */ 41 | 42 | static gboolean key_press (GtkWidget * invisible, GdkEventKey * event, gpointer data); 43 | static gboolean mouse_press (GtkWidget * invisible, GdkEventButton * event, gpointer data); 44 | 45 | static GdkCursor * 46 | make_picker_cursor (GdkScreen * screen) 47 | { 48 | GdkDisplay *display; 49 | GdkCursor *cursor; 50 | 51 | display = gdk_screen_get_display (screen); 52 | cursor = gdk_cursor_new_from_name (display, "color-picker"); 53 | if (!cursor) 54 | cursor = gdk_cursor_new_from_name (display, "cell"); 55 | if (!cursor) 56 | g_printerr ("cpicker: cannot create cursor\n"); 57 | return cursor; 58 | } 59 | 60 | static void 61 | grab_color_at_pointer (GdkScreen * screen, GdkDevice * device, gint x_root, gint y_root, gpointer data) 62 | { 63 | GdkPixbuf *pixbuf; 64 | guchar *pixels; 65 | GdkRGBA color; 66 | GdkWindow *root_window = gdk_screen_get_root_window (screen); 67 | GrabData *gd = (GrabData *) data; 68 | 69 | pixbuf = gdk_pixbuf_get_from_window (root_window, x_root, y_root, 1, 1); 70 | if (!pixbuf) 71 | { 72 | gint x, y; 73 | GdkWindow *window = gdk_device_get_window_at_position (device, &x, &y); 74 | if (!window) 75 | return; 76 | pixbuf = gdk_pixbuf_get_from_window (window, x, y, 1, 1); 77 | if (!pixbuf) 78 | return; 79 | } 80 | pixels = gdk_pixbuf_get_pixels (pixbuf); 81 | color.red = pixels[0] / 255.; 82 | color.green = pixels[1] / 255.; 83 | color.blue = pixels[2] / 255.; 84 | color.alpha = 1.0; 85 | g_object_unref (pixbuf); 86 | 87 | if (gd->color_widget) 88 | gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (gd->color_widget), &color); 89 | else 90 | g_print ("#%02X%02X%02X\n", (gint) (color.red * 255), (gint) (color.green * 255), (gint) (color.blue * 255)); 91 | } 92 | 93 | static void 94 | shutdown_eyedropper (gpointer data) 95 | { 96 | GrabData *gd = (GrabData *) data; 97 | 98 | if (gd->has_grab) 99 | { 100 | gdk_device_ungrab (gd->keyb_device, gd->time); 101 | gdk_device_ungrab (gd->pointer_device, gd->time); 102 | gtk_device_grab_remove (gd->grab_widget, gd->pointer_device); 103 | } 104 | 105 | if (gd->color_widget == NULL) 106 | gtk_main_quit (); 107 | } 108 | 109 | static void 110 | mouse_motion (GtkWidget * invisible, GdkEventMotion * event, gpointer data) 111 | { 112 | grab_color_at_pointer (gdk_event_get_screen ((GdkEvent *) event), 113 | gdk_event_get_device ((GdkEvent *) event), event->x_root, event->y_root, data); 114 | } 115 | 116 | static gboolean 117 | mouse_release (GtkWidget * invisible, GdkEventButton * event, gpointer data) 118 | { 119 | /* GtkColorSelection *colorsel = data; */ 120 | 121 | if (event->button != GDK_BUTTON_PRIMARY) 122 | return FALSE; 123 | 124 | grab_color_at_pointer (gdk_event_get_screen ((GdkEvent *) event), 125 | gdk_event_get_device ((GdkEvent *) event), event->x_root, event->y_root, data); 126 | 127 | shutdown_eyedropper (data); 128 | 129 | g_signal_handlers_disconnect_by_func (invisible, mouse_motion, data); 130 | g_signal_handlers_disconnect_by_func (invisible, mouse_release, data); 131 | 132 | return TRUE; 133 | } 134 | 135 | /* Helper Functions */ 136 | 137 | static gboolean 138 | key_press (GtkWidget * invisible, GdkEventKey * event, gpointer data) 139 | { 140 | GdkScreen *screen = gdk_event_get_screen ((GdkEvent *) event); 141 | GdkDevice *device, *pointer_device; 142 | guint state = event->state & gtk_accelerator_get_default_mod_mask (); 143 | gint x, y, dx, dy; 144 | 145 | device = gdk_event_get_device ((GdkEvent *) event); 146 | pointer_device = gdk_device_get_associated_device (device); 147 | gdk_device_get_position (pointer_device, NULL, &x, &y); 148 | 149 | dx = dy = 0; 150 | 151 | switch (event->keyval) 152 | { 153 | case GDK_KEY_space: 154 | case GDK_KEY_Return: 155 | case GDK_KEY_ISO_Enter: 156 | case GDK_KEY_KP_Enter: 157 | case GDK_KEY_KP_Space: 158 | grab_color_at_pointer (screen, pointer_device, x, y, data); 159 | /* fall through */ 160 | 161 | case GDK_KEY_Escape: 162 | shutdown_eyedropper (data); 163 | 164 | g_signal_handlers_disconnect_by_func (invisible, mouse_press, data); 165 | g_signal_handlers_disconnect_by_func (invisible, key_press, data); 166 | 167 | return TRUE; 168 | 169 | case GDK_KEY_Up: 170 | case GDK_KEY_KP_Up: 171 | dy = state == GDK_MOD1_MASK ? -BIG_STEP : -1; 172 | break; 173 | 174 | case GDK_KEY_Down: 175 | case GDK_KEY_KP_Down: 176 | dy = state == GDK_MOD1_MASK ? BIG_STEP : 1; 177 | break; 178 | 179 | case GDK_KEY_Left: 180 | case GDK_KEY_KP_Left: 181 | dx = state == GDK_MOD1_MASK ? -BIG_STEP : -1; 182 | break; 183 | 184 | case GDK_KEY_Right: 185 | case GDK_KEY_KP_Right: 186 | dx = state == GDK_MOD1_MASK ? BIG_STEP : 1; 187 | break; 188 | 189 | default: 190 | return FALSE; 191 | } 192 | 193 | gdk_device_warp (pointer_device, screen, x + dx, y + dy); 194 | 195 | return TRUE; 196 | } 197 | 198 | static gboolean 199 | mouse_press (GtkWidget * invisible, GdkEventButton * event, gpointer data) 200 | { 201 | if (event->type == GDK_BUTTON_PRESS && event->button == GDK_BUTTON_PRIMARY) 202 | { 203 | g_signal_connect (invisible, "motion-notify-event", G_CALLBACK (mouse_motion), data); 204 | g_signal_connect (invisible, "button-release-event", G_CALLBACK (mouse_release), data); 205 | g_signal_handlers_disconnect_by_func (invisible, mouse_press, data); 206 | g_signal_handlers_disconnect_by_func (invisible, key_press, data); 207 | return TRUE; 208 | } 209 | 210 | return FALSE; 211 | } 212 | 213 | void 214 | yad_get_screen_color (GtkWidget *widget) 215 | { 216 | GrabData *gd; 217 | GdkScreen *screen; 218 | GdkDevice *device; 219 | GdkCursor *picker_cursor; 220 | GdkGrabStatus grab_status; 221 | GdkWindow *window; 222 | 223 | gd = g_new0 (GrabData, 1); 224 | gd->color_widget = widget; 225 | gd->time = gtk_get_current_event_time (); 226 | 227 | screen = gdk_screen_get_default (); 228 | device = gtk_get_current_event_device (); 229 | 230 | if (device) 231 | { 232 | if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD) 233 | { 234 | gd->keyb_device = device; 235 | gd->pointer_device = gdk_device_get_associated_device (device); 236 | } 237 | else 238 | { 239 | gd->pointer_device = device; 240 | gd->keyb_device = gdk_device_get_associated_device (device); 241 | } 242 | } 243 | else 244 | { 245 | GdkSeat *seat = gdk_display_get_default_seat (gdk_screen_get_display (screen)); 246 | gd->keyb_device = gdk_seat_get_keyboard (seat); 247 | gd->pointer_device = gdk_seat_get_pointer (seat); 248 | } 249 | 250 | gd->grab_widget = gtk_window_new (GTK_WINDOW_POPUP); 251 | gtk_window_set_screen (GTK_WINDOW (gd->grab_widget), screen); 252 | gtk_window_resize (GTK_WINDOW (gd->grab_widget), 1, 1); 253 | gtk_window_move (GTK_WINDOW (gd->grab_widget), -100, -100); 254 | gtk_widget_show (gd->grab_widget); 255 | 256 | gtk_widget_add_events (gd->grab_widget, GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK); 257 | 258 | window = gtk_widget_get_window (gd->grab_widget); 259 | if (gdk_device_grab (gd->keyb_device, window, GDK_OWNERSHIP_APPLICATION, FALSE, 260 | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK, NULL, gd->time) != GDK_GRAB_SUCCESS) 261 | return; 262 | 263 | picker_cursor = make_picker_cursor (screen); 264 | grab_status = gdk_device_grab (gd->pointer_device, window, GDK_OWNERSHIP_APPLICATION, FALSE, 265 | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK, 266 | picker_cursor, gd->time); 267 | if (picker_cursor) 268 | g_object_unref (picker_cursor); 269 | 270 | if (grab_status != GDK_GRAB_SUCCESS) 271 | { 272 | gdk_device_ungrab (gd->keyb_device, gd->time); 273 | return; 274 | } 275 | 276 | gtk_device_grab_add (gd->grab_widget, gd->pointer_device, TRUE); 277 | 278 | gd->has_grab = TRUE; 279 | 280 | g_signal_connect (gd->grab_widget, "button-press-event", G_CALLBACK (mouse_press), gd); 281 | g_signal_connect (gd->grab_widget, "key-press-event", G_CALLBACK (key_press), gd); 282 | } 283 | -------------------------------------------------------------------------------- /src/cpicker.h: -------------------------------------------------------------------------------- 1 | #ifndef __CPICKER_H__ 2 | #define __CPICKER_H__ 3 | 4 | #include 5 | 6 | void yad_get_screen_color (GtkWidget *widget); 7 | 8 | #endif /* __CPICKER_H__ */ 9 | -------------------------------------------------------------------------------- /src/cpicker_gtk2.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * This file is part of YAD. 4 | * 5 | * YAD is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * YAD is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with YAD. If not, see . 17 | * 18 | * Copyright (C) 2023, step 19 | */ 20 | 21 | /* Some code adapted from GtkColorSelection widget (gtk/gtkcolorsel.c GTK+-2.24.33) */ 22 | 23 | #define GDK_DISABLE_DEPRECATION_WARNINGS 24 | 25 | #include "cpicker.h" 26 | #include 27 | 28 | #define GDK_BUTTON_PRIMARY (1) 29 | 30 | typedef struct { 31 | GtkWidget *grab_widget; 32 | gboolean has_grab; 33 | guint32 time; 34 | } GrabData; 35 | 36 | static gboolean key_press (GtkWidget * invisible, GdkEventKey * event, gpointer data); 37 | static gboolean mouse_press (GtkWidget * invisible, GdkEventButton * event, gpointer data); 38 | 39 | static GdkCursor * 40 | make_picker_cursor (GdkScreen * screen) 41 | { 42 | GdkDisplay *display; 43 | GdkCursor *cursor; 44 | 45 | display = gdk_screen_get_display (screen); 46 | cursor = gdk_cursor_new_from_name (display, "color-picker"); 47 | if (!cursor) 48 | cursor = gdk_cursor_new_from_name (display, "crosshair"); 49 | if (!cursor) 50 | g_printerr ("cpicker: cannot create cursor\n"); 51 | return cursor; 52 | } 53 | 54 | static void 55 | grab_color_at_pointer (GdkScreen * screen, gint x_root, gint y_root, gpointer data) 56 | { 57 | GdkPixbuf *pixbuf; 58 | guchar *pixels; 59 | GdkColor color; 60 | GdkWindow *root_window = gdk_screen_get_root_window (screen); 61 | GrabData *gd = (GrabData *) data; 62 | 63 | pixbuf = gdk_pixbuf_get_from_drawable (NULL, root_window, NULL, x_root, y_root, 0, 0, 1, 1); 64 | if (!pixbuf) 65 | { 66 | gint x, y; 67 | GdkDisplay *display = gdk_screen_get_display (screen); 68 | GdkWindow *window = gdk_display_get_window_at_pointer (display, &x, &y); 69 | if (!window) 70 | return; 71 | pixbuf = gdk_pixbuf_get_from_drawable (NULL, window, NULL, x, y, 0, 0, 1, 1); 72 | if (!pixbuf) 73 | return; 74 | } 75 | pixels = gdk_pixbuf_get_pixels (pixbuf); 76 | color.red = pixels[0] & 0xFF; 77 | color.green = pixels[1] & 0xFF; 78 | color.blue = pixels[2] & 0xFF; 79 | g_object_unref (pixbuf); 80 | 81 | g_print ("#%02X%02X%02X\n", (gint) color.red, (gint) color.green, (gint) color.blue); 82 | } 83 | 84 | static void 85 | shutdown (gpointer data) 86 | { 87 | GrabData *gd = (GrabData *) data; 88 | 89 | if (gd->has_grab) 90 | { 91 | GdkDisplay *display = gtk_widget_get_display (gd->grab_widget); 92 | gdk_display_keyboard_ungrab (display, gd->time); 93 | gdk_display_pointer_ungrab (display, gd->time); 94 | gtk_grab_remove (gd->grab_widget); 95 | gd->has_grab = FALSE; 96 | } 97 | 98 | gtk_main_quit (); 99 | } 100 | 101 | static void 102 | mouse_motion (GtkWidget * invisible, GdkEventMotion * event, gpointer data) 103 | { 104 | grab_color_at_pointer (gdk_event_get_screen ((GdkEvent *) event), 105 | event->x_root, event->y_root, data); 106 | } 107 | 108 | static gboolean 109 | mouse_release (GtkWidget * invisible, GdkEventButton * event, gpointer data) 110 | { 111 | /* GrabData *gd = data; */ 112 | 113 | if (event->button != GDK_BUTTON_PRIMARY) 114 | return FALSE; 115 | 116 | grab_color_at_pointer (gdk_event_get_screen ((GdkEvent *) event), 117 | event->x_root, event->y_root, data); 118 | 119 | shutdown (data); 120 | 121 | g_signal_handlers_disconnect_by_func (invisible, mouse_motion, data); 122 | g_signal_handlers_disconnect_by_func (invisible, mouse_release, data); 123 | 124 | return TRUE; 125 | } 126 | 127 | /* Helper Functions */ 128 | 129 | static gboolean 130 | key_press (GtkWidget * invisible, GdkEventKey * event, gpointer data) 131 | { 132 | GdkDisplay *display = gtk_widget_get_display (invisible); 133 | GdkScreen *screen = gdk_event_get_screen ((GdkEvent *) event); 134 | guint state = event->state & gtk_accelerator_get_default_mod_mask (); 135 | gint x, y, dx, dy; 136 | 137 | gdk_display_get_pointer (display, NULL, &x, &y, NULL); 138 | 139 | dx = dy = 0; 140 | 141 | switch (event->keyval) 142 | { 143 | case GDK_space: 144 | case GDK_Return: 145 | case GDK_ISO_Enter: 146 | case GDK_KP_Enter: 147 | case GDK_KP_Space: 148 | grab_color_at_pointer (screen, x, y, data); 149 | /* fall through */ 150 | 151 | case GDK_Escape: 152 | shutdown (data); 153 | 154 | g_signal_handlers_disconnect_by_func (invisible, mouse_press, data); 155 | g_signal_handlers_disconnect_by_func (invisible, key_press, data); 156 | 157 | return TRUE; 158 | 159 | default: 160 | return FALSE; 161 | } 162 | 163 | gdk_display_warp_pointer (display, screen, x + dx, y + dy); 164 | 165 | return TRUE; 166 | } 167 | 168 | static gboolean 169 | mouse_press (GtkWidget * invisible, GdkEventButton * event, gpointer data) 170 | { 171 | if (event->type == GDK_BUTTON_PRESS && event->button == GDK_BUTTON_PRIMARY) 172 | { 173 | g_signal_connect (invisible, "motion-notify-event", G_CALLBACK (mouse_motion), data); 174 | g_signal_connect (invisible, "button-release-event", G_CALLBACK (mouse_release), data); 175 | g_signal_handlers_disconnect_by_func (invisible, mouse_press, data); 176 | g_signal_handlers_disconnect_by_func (invisible, key_press, data); 177 | return TRUE; 178 | } 179 | 180 | return FALSE; 181 | } 182 | 183 | void 184 | yad_get_screen_color (GtkWidget *widget) 185 | { 186 | GrabData *gd; 187 | GdkScreen *screen; 188 | GdkCursor *picker_cursor; 189 | GdkGrabStatus grab_status; 190 | GdkWindow *window; 191 | 192 | gd = g_new0 (GrabData, 1); 193 | gd->time = GDK_CURRENT_TIME; 194 | 195 | screen = gdk_screen_get_default (); 196 | gd->grab_widget = gtk_window_new (GTK_WINDOW_POPUP); 197 | gtk_window_set_screen (GTK_WINDOW (gd->grab_widget), screen); 198 | gtk_window_resize (GTK_WINDOW (gd->grab_widget), 1, 1); 199 | gtk_window_move (GTK_WINDOW (gd->grab_widget), -100, -100); 200 | gtk_widget_show (gd->grab_widget); 201 | 202 | gtk_widget_add_events (gd->grab_widget, GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK); 203 | 204 | window = gtk_widget_get_window (gd->grab_widget); 205 | if (gdk_keyboard_grab (window, 206 | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK, gd->time) != GDK_GRAB_SUCCESS) 207 | return; 208 | 209 | picker_cursor = make_picker_cursor (screen); 210 | grab_status = gdk_pointer_grab (window, FALSE, 211 | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK, 212 | NULL, picker_cursor, gd->time); 213 | gdk_cursor_unref (picker_cursor); 214 | 215 | if (grab_status != GDK_GRAB_SUCCESS) 216 | { 217 | gdk_keyboard_ungrab (gd->time); 218 | return; 219 | } 220 | 221 | gd->has_grab = TRUE; 222 | 223 | g_signal_connect (gd->grab_widget, "button-press-event", G_CALLBACK (mouse_press), gd); 224 | g_signal_connect (gd->grab_widget, "key-press-event", G_CALLBACK (key_press), gd); 225 | } 226 | -------------------------------------------------------------------------------- /src/dnd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of YAD. 3 | * 4 | * YAD 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 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * YAD is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with YAD. If not, see . 16 | * 17 | * Copyright (C) 2008-2019, Victor Ananjevsky 18 | */ 19 | 20 | #include "yad.h" 21 | 22 | static void 23 | drop_data_cb (GtkWidget * w, GdkDragContext * dc, gint x, gint y, 24 | GtkSelectionData * sel, guint info, guint t, gpointer data) 25 | { 26 | GdkAtom stgt; 27 | static guint drop_cnt = 0; 28 | 29 | stgt = gtk_selection_data_get_target (sel); 30 | 31 | if (gtk_targets_include_uri (&stgt, 1)) 32 | { 33 | gchar **uris; 34 | gint i = 0; 35 | 36 | uris = gtk_selection_data_get_uris (sel); 37 | if (!uris) 38 | return; 39 | 40 | while (uris[i]) 41 | { 42 | gchar *dstr = g_uri_unescape_string (uris[i], NULL); 43 | if (options.common_data.command) 44 | { 45 | gchar *action; 46 | 47 | if (g_strstr_len (options.common_data.command, -1, "%s")) 48 | action = g_strdup_printf (options.common_data.command, dstr); 49 | else 50 | action = g_strdup_printf ("%s '%s'", options.common_data.command, dstr); 51 | run_command_async (action); 52 | g_free (action); 53 | } 54 | else 55 | { 56 | g_printf ("%s\n", dstr); 57 | fflush (stdout); 58 | } 59 | g_free (dstr); 60 | i++; 61 | } 62 | g_strfreev (uris); 63 | } 64 | else if (gtk_targets_include_text (&stgt, 1)) 65 | { 66 | guchar *str = gtk_selection_data_get_text (sel); 67 | if (str) 68 | { 69 | gchar *dstr = g_uri_unescape_string ((const gchar *) str, NULL); 70 | if (options.common_data.command) 71 | { 72 | gchar *action, *arg; 73 | 74 | arg = g_shell_quote (dstr); 75 | if (g_strstr_len (options.common_data.command, -1, "%s")) 76 | action = g_strdup_printf (options.common_data.command, arg); 77 | else 78 | action = g_strdup_printf ("%s %s", options.common_data.command, arg); 79 | g_free (arg); 80 | 81 | run_command_async (action); 82 | g_free (action); 83 | } 84 | else 85 | { 86 | g_printf ("%s\n", dstr); 87 | fflush (stdout); 88 | } 89 | g_free (dstr); 90 | g_free (str); 91 | } 92 | } 93 | 94 | if (options.dnd_data.exit_on_drop) 95 | { 96 | drop_cnt++; 97 | if (drop_cnt == options.dnd_data.exit_on_drop) 98 | yad_exit (options.data.def_resp); 99 | } 100 | } 101 | 102 | void 103 | dnd_init (GtkWidget * w) 104 | { 105 | GtkTargetList *tlist; 106 | GtkTargetEntry *tgts; 107 | gint ntgts; 108 | 109 | tlist = gtk_target_list_new (NULL, 0); 110 | gtk_target_list_add_uri_targets (tlist, 0); 111 | gtk_target_list_add_text_targets (tlist, 0); 112 | 113 | tgts = gtk_target_table_new_from_list (tlist, &ntgts); 114 | 115 | gtk_drag_dest_set (w, GTK_DEST_DEFAULT_ALL, tgts, ntgts, GDK_ACTION_COPY | GDK_ACTION_MOVE); 116 | g_signal_connect (G_OBJECT (w), "drag_data_received", G_CALLBACK (drop_data_cb), NULL); 117 | 118 | gtk_target_table_free (tgts, ntgts); 119 | gtk_target_list_unref (tlist); 120 | 121 | /* set tooltip */ 122 | if (options.dnd_data.tooltip) 123 | { 124 | if (!options.data.no_markup) 125 | gtk_widget_set_tooltip_markup (w, options.data.dialog_text); 126 | else 127 | gtk_widget_set_tooltip_text (w, options.data.dialog_text); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/entry.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of YAD. 3 | * 4 | * YAD 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 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * YAD is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with YAD. If not, see . 16 | * 17 | * Copyright (C) 2008-2019, Victor Ananjevsky 18 | */ 19 | 20 | #include "yad.h" 21 | 22 | static GtkWidget *entry; 23 | static gboolean is_combo = FALSE; 24 | 25 | static void 26 | entry_activate_cb (GtkEntry * entry, gpointer data) 27 | { 28 | if (options.plug == -1) 29 | yad_exit (options.data.def_resp); 30 | } 31 | 32 | static gboolean 33 | combo_activate_cb (GtkWidget * w, GdkEventKey * ev, gpointer data) 34 | { 35 | if (ev->keyval == GDK_KEY_Return || ev->keyval == GDK_KEY_KP_Enter) 36 | { 37 | if (options.plug == -1) 38 | yad_exit (options.data.def_resp); 39 | return TRUE; 40 | } 41 | return FALSE; 42 | } 43 | 44 | static void 45 | icon_cb (GtkEntry * entry, GtkEntryIconPosition pos, GdkEventButton * event, gpointer data) 46 | { 47 | if (event->button == 1) 48 | { 49 | gchar *cmd = NULL; 50 | 51 | switch (pos) 52 | { 53 | case GTK_ENTRY_ICON_PRIMARY: 54 | cmd = options.entry_data.licon_action; 55 | break; 56 | case GTK_ENTRY_ICON_SECONDARY: 57 | cmd = options.entry_data.ricon_action; 58 | break; 59 | } 60 | 61 | if (cmd) 62 | { 63 | FILE *pf; 64 | gchar buf[1024]; 65 | GString *str; 66 | 67 | str = g_string_new (""); 68 | pf = popen (cmd, "r"); 69 | while (fgets (buf, sizeof (buf), pf)) 70 | g_string_append (str, buf); 71 | if (pclose (pf) == 0) 72 | { 73 | if (str->str[str->len - 1] == '\n') 74 | str->str[str->len - 1] = '\0'; 75 | gtk_entry_set_text (GTK_ENTRY (entry), str->str); 76 | } 77 | g_string_free (str, TRUE); 78 | } 79 | else 80 | gtk_entry_set_text (GTK_ENTRY (entry), ""); 81 | 82 | /* move cursor to the end of text */ 83 | gtk_editable_set_position (GTK_EDITABLE (entry), -1); 84 | } 85 | } 86 | 87 | static GtkTreeModel * 88 | create_completion_model (void) 89 | { 90 | GtkListStore *store; 91 | GtkTreeIter iter; 92 | gint i = 0; 93 | 94 | store = gtk_list_store_new (1, G_TYPE_STRING); 95 | 96 | if (options.extra_data) 97 | { 98 | while (options.extra_data[i] != NULL) 99 | { 100 | gtk_list_store_append (store, &iter); 101 | gtk_list_store_set (store, &iter, 0, options.extra_data[i], -1); 102 | i++; 103 | } 104 | } 105 | 106 | return GTK_TREE_MODEL (store); 107 | } 108 | 109 | GtkWidget * 110 | entry_create_widget (GtkWidget * dlg) 111 | { 112 | GtkWidget *c, *l = NULL, *w = NULL; 113 | 114 | #if !GTK_CHECK_VERSION(3,0,0) 115 | w = gtk_hbox_new (FALSE, 5); 116 | #else 117 | w = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); 118 | #endif 119 | 120 | if (options.entry_data.entry_label) 121 | { 122 | l = gtk_label_new (NULL); 123 | if (options.data.no_markup) 124 | gtk_label_set_text_with_mnemonic (GTK_LABEL (l), options.entry_data.entry_label); 125 | else 126 | gtk_label_set_markup_with_mnemonic (GTK_LABEL (l), options.entry_data.entry_label); 127 | gtk_widget_set_name (l, "yad-entry-label"); 128 | gtk_box_pack_start (GTK_BOX (w), l, FALSE, FALSE, 1); 129 | } 130 | 131 | if (options.entry_data.numeric) 132 | { 133 | gdouble min, max, step, val; 134 | guint prec; 135 | 136 | min = 0.0; 137 | max = 65535.0; 138 | step = 1.0; 139 | prec = 0; 140 | val = 0.0; 141 | 142 | if (options.extra_data && options.extra_data[0]) 143 | { 144 | min = g_ascii_strtod (options.extra_data[0], NULL); 145 | if (options.extra_data[1]) 146 | { 147 | max = g_ascii_strtod (options.extra_data[1], NULL); 148 | if (options.extra_data[2]) 149 | { 150 | step = g_ascii_strtod (options.extra_data[2], NULL); 151 | if (options.extra_data[3]) 152 | { 153 | prec = (guint) g_ascii_strtoull (options.extra_data[3], NULL, 0); 154 | if (prec > 20) 155 | prec = 20; 156 | } 157 | } 158 | } 159 | } 160 | 161 | c = entry = gtk_spin_button_new_with_range (min, max, step); 162 | gtk_entry_set_alignment (GTK_ENTRY (c), 1.0); 163 | gtk_spin_button_set_digits (GTK_SPIN_BUTTON (c), prec); 164 | gtk_widget_set_name (entry, "yad-entry-spin"); 165 | 166 | if (options.entry_data.entry_text) 167 | { 168 | val = g_ascii_strtod (options.entry_data.entry_text, NULL); 169 | 170 | if (min >= max) 171 | { 172 | g_printerr (_("Maximum value must be greater than minimum value.\n")); 173 | min = 0.0; 174 | max = 65535.0; 175 | } 176 | 177 | if (val < min) 178 | { 179 | g_printerr (_("Initial value less than minimal.\n")); 180 | val = min; 181 | } 182 | else if (val > max) 183 | { 184 | g_printerr (_("Initial value greater than maximum.\n")); 185 | val = max; 186 | } 187 | } 188 | 189 | gtk_spin_button_set_value (GTK_SPIN_BUTTON (c), val); 190 | } 191 | else if (!options.entry_data.completion && options.extra_data && *options.extra_data) 192 | { 193 | gint active, i; 194 | 195 | if (options.common_data.editable || settings.combo_always_editable) 196 | { 197 | c = gtk_combo_box_text_new_with_entry (); 198 | gtk_widget_set_name (c, "yad-entry-edit-combo"); 199 | entry = gtk_bin_get_child (GTK_BIN (c)); 200 | if (options.entry_data.licon) 201 | { 202 | GdkPixbuf *pb = get_pixbuf (options.entry_data.licon, YAD_SMALL_ICON, TRUE); 203 | 204 | if (pb) 205 | gtk_entry_set_icon_from_pixbuf (GTK_ENTRY (entry), GTK_ENTRY_ICON_PRIMARY, pb); 206 | } 207 | if (options.entry_data.ricon) 208 | { 209 | GdkPixbuf *pb = get_pixbuf (options.entry_data.ricon, YAD_SMALL_ICON, TRUE); 210 | 211 | if (pb) 212 | gtk_entry_set_icon_from_pixbuf (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY, pb); 213 | } 214 | } 215 | else 216 | { 217 | c = entry = gtk_combo_box_text_new (); 218 | gtk_widget_set_name (c, "yad-entry-combo"); 219 | is_combo = TRUE; 220 | } 221 | 222 | i = 0; 223 | active = -1; 224 | while (options.extra_data[i] != NULL) 225 | { 226 | if (options.entry_data.entry_text && 227 | g_ascii_strcasecmp (options.extra_data[i], options.entry_data.entry_text) == 0) 228 | active = i; 229 | gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (c), options.extra_data[i]); 230 | i++; 231 | } 232 | 233 | if (options.entry_data.entry_text && active == -1) 234 | { 235 | gtk_combo_box_text_prepend_text (GTK_COMBO_BOX_TEXT (c), options.entry_data.entry_text); 236 | } 237 | 238 | /* set first iter active */ 239 | if (!options.common_data.editable) 240 | gtk_combo_box_set_active (GTK_COMBO_BOX (c), (active != -1 ? active : 0)); 241 | } 242 | else 243 | { 244 | c = entry = gtk_entry_new (); 245 | gtk_widget_set_name (c, "yad-entry-widget"); 246 | 247 | gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE); 248 | 249 | if (options.entry_data.entry_text) 250 | gtk_entry_set_text (GTK_ENTRY (entry), options.entry_data.entry_text); 251 | 252 | if (options.common_data.hide_text) 253 | g_object_set (G_OBJECT (entry), "visibility", FALSE, NULL); 254 | 255 | if (options.entry_data.completion) 256 | { 257 | GtkEntryCompletion *completion; 258 | GtkTreeModel *completion_model; 259 | 260 | completion = gtk_entry_completion_new (); 261 | gtk_entry_set_completion (GTK_ENTRY (entry), completion); 262 | 263 | completion_model = create_completion_model (); 264 | gtk_entry_completion_set_model (completion, completion_model); 265 | g_object_unref (completion_model); 266 | 267 | gtk_entry_completion_set_text_column (completion, 0); 268 | 269 | if (options.common_data.complete != YAD_COMPLETE_SIMPLE) 270 | gtk_entry_completion_set_match_func (completion, check_complete, NULL, NULL); 271 | 272 | g_object_unref (completion); 273 | } 274 | 275 | if (options.entry_data.licon) 276 | { 277 | GdkPixbuf *pb = get_pixbuf (options.entry_data.licon, YAD_SMALL_ICON, TRUE); 278 | 279 | if (pb) 280 | gtk_entry_set_icon_from_pixbuf (GTK_ENTRY (entry), GTK_ENTRY_ICON_PRIMARY, pb); 281 | } 282 | if (options.entry_data.ricon) 283 | { 284 | GdkPixbuf *pb = get_pixbuf (options.entry_data.ricon, YAD_SMALL_ICON, TRUE); 285 | 286 | if (pb) 287 | gtk_entry_set_icon_from_pixbuf (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY, pb); 288 | } 289 | } 290 | 291 | if (l) 292 | gtk_label_set_mnemonic_widget (GTK_LABEL (l), entry); 293 | 294 | if (!is_combo) 295 | g_signal_connect (G_OBJECT (entry), "activate", G_CALLBACK (entry_activate_cb), dlg); 296 | else 297 | g_signal_connect (G_OBJECT (entry), "key-press-event", G_CALLBACK (combo_activate_cb), dlg); 298 | 299 | if (options.entry_data.licon || options.entry_data.ricon) 300 | g_signal_connect (G_OBJECT (entry), "icon-press", G_CALLBACK (icon_cb), NULL); 301 | 302 | gtk_box_pack_start (GTK_BOX (w), c, TRUE, TRUE, 1); 303 | 304 | return w; 305 | } 306 | 307 | void 308 | entry_print_result (void) 309 | { 310 | if (options.entry_data.numeric) 311 | { 312 | guint prec = gtk_spin_button_get_digits (GTK_SPIN_BUTTON (entry)); 313 | g_print ("%.*f\n", prec, gtk_spin_button_get_value (GTK_SPIN_BUTTON (entry))); 314 | } 315 | else if (is_combo) 316 | { 317 | if (options.common_data.num_output) 318 | g_print ("%d\n", gtk_combo_box_get_active (GTK_COMBO_BOX (entry)) + 1); 319 | else 320 | { 321 | g_print ("%s\n", gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (entry))); 322 | } 323 | } 324 | else 325 | g_print ("%s\n", gtk_entry_get_text (GTK_ENTRY (entry))); 326 | } 327 | -------------------------------------------------------------------------------- /src/file.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of YAD. 3 | * 4 | * YAD 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 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * YAD is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with YAD. If not, see . 16 | * 17 | * Copyright (C) 2008-2019, Victor Ananjevsky 18 | */ 19 | 20 | #include "yad.h" 21 | 22 | static GtkWidget *filechooser; 23 | 24 | static void 25 | file_activated_cb (GtkFileChooser * chooser, gpointer data) 26 | { 27 | if (options.plug == -1) 28 | yad_exit (options.data.def_resp); 29 | } 30 | 31 | gboolean 32 | file_confirm_overwrite (GtkWidget * dlg) 33 | { 34 | if (options.file_data.save && options.file_data.confirm_overwrite && !options.common_data.multi) 35 | { 36 | gchar *filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (filechooser)); 37 | 38 | if (g_file_test (filename, G_FILE_TEST_EXISTS)) 39 | { 40 | GtkWidget *d; 41 | gint r; 42 | gchar *buf; 43 | 44 | buf = g_strcompress (options.file_data.confirm_text); 45 | d = gtk_message_dialog_new (GTK_WINDOW (dlg), GTK_DIALOG_DESTROY_WITH_PARENT, 46 | GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, "%s", buf); 47 | g_free (buf); 48 | r = gtk_dialog_run (GTK_DIALOG (d)); 49 | gtk_widget_destroy (d); 50 | if (r != GTK_RESPONSE_YES) 51 | return FALSE; 52 | } 53 | } 54 | 55 | return TRUE; 56 | } 57 | 58 | GtkWidget * 59 | file_create_widget (GtkWidget * dlg) 60 | { 61 | GtkWidget *w; 62 | GList *filt; 63 | GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN; 64 | 65 | if (options.file_data.directory) 66 | { 67 | if (options.file_data.save) 68 | action = GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER; 69 | else 70 | action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; 71 | } 72 | else 73 | { 74 | if (options.file_data.save) 75 | action = GTK_FILE_CHOOSER_ACTION_SAVE; 76 | } 77 | 78 | w = filechooser = gtk_file_chooser_widget_new (action); 79 | gtk_widget_set_name (w, "yad-file-widget"); 80 | 81 | if (options.common_data.uri) 82 | { 83 | if (!options.file_data.directory && g_file_test (options.common_data.uri, G_FILE_TEST_IS_DIR)) 84 | gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (w), options.common_data.uri); 85 | else 86 | { 87 | gchar *dir = g_path_get_dirname (options.common_data.uri); 88 | 89 | if (g_path_is_absolute (options.common_data.uri) == TRUE) 90 | gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (w), dir); 91 | 92 | if (options.common_data.uri[strlen (options.common_data.uri) - 1] != '/') 93 | { 94 | gchar *basename = g_path_get_basename (options.common_data.uri); 95 | if (options.file_data.save) 96 | gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (w), basename); 97 | else 98 | gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (w), options.common_data.uri); 99 | g_free (basename); 100 | } 101 | g_free (dir); 102 | } 103 | } 104 | else 105 | gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (w), g_get_current_dir ()); 106 | 107 | if (options.common_data.multi) 108 | gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (w), TRUE); 109 | 110 | /* add preview */ 111 | if (options.common_data.preview) 112 | { 113 | GtkWidget *p = gtk_image_new (); 114 | gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER (w), p); 115 | g_signal_connect (w, "update-preview", G_CALLBACK (update_preview), p); 116 | } 117 | 118 | /* add filters */ 119 | for (filt = options.common_data.filters; filt; filt = filt->next) 120 | gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (w), GTK_FILE_FILTER (filt->data)); 121 | 122 | g_signal_connect (w, "map", G_CALLBACK (gtk_file_chooser_set_show_hidden), GINT_TO_POINTER (options.common_data.show_hidden)); 123 | g_signal_connect (w, "file-activated", G_CALLBACK (file_activated_cb), dlg); 124 | 125 | return w; 126 | } 127 | 128 | void 129 | file_print_result (void) 130 | { 131 | GSList *selections, *iter; 132 | 133 | selections = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (filechooser)); 134 | for (iter = selections; iter != NULL; iter = iter->next) 135 | { 136 | if (options.common_data.quoted_output) 137 | { 138 | gchar *buf = g_shell_quote (g_filename_to_utf8 ((gchar *) iter->data, -1, NULL, NULL, NULL)); 139 | g_printf ("%s", buf); 140 | g_free (buf); 141 | } 142 | else 143 | g_printf ("%s", g_filename_to_utf8 ((gchar *) iter->data, -1, NULL, NULL, NULL)); 144 | g_free (iter->data); 145 | if (iter->next != NULL) 146 | g_printf ("%s", options.common_data.separator); 147 | } 148 | g_printf ("\n"); 149 | g_slist_free (selections); 150 | } 151 | -------------------------------------------------------------------------------- /src/font.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of YAD. 3 | * 4 | * YAD 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 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * YAD is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with YAD. If not, see . 16 | * 17 | * Copyright (C) 2008-2019, Victor Ananjevsky 18 | */ 19 | 20 | #include "yad.h" 21 | 22 | static GtkWidget *font; 23 | 24 | static void 25 | realize_cb (GtkWidget * w, gpointer d) 26 | { 27 | #if GTK_CHECK_VERSION(3,2,0) 28 | gtk_font_chooser_set_font (GTK_FONT_CHOOSER (w), options.common_data.font); 29 | #else 30 | gtk_font_selection_set_font_name (GTK_FONT_SELECTION (w), options.common_data.font); 31 | #endif 32 | } 33 | 34 | GtkWidget * 35 | font_create_widget (GtkWidget * dlg) 36 | { 37 | GtkWidget *w; 38 | 39 | #if GTK_CHECK_VERSION(3,2,0) 40 | w = font = gtk_font_chooser_widget_new (); 41 | #else 42 | w = font = gtk_font_selection_new (); 43 | #endif 44 | gtk_widget_set_name (w, "yad-font-widget"); 45 | 46 | if (options.font_data.preview) 47 | #if GTK_CHECK_VERSION(3,2,0) 48 | gtk_font_chooser_set_preview_text (GTK_FONT_CHOOSER (w), options.font_data.preview); 49 | #else 50 | gtk_font_selection_set_preview_text (GTK_FONT_SELECTION (w), options.font_data.preview); 51 | #endif 52 | 53 | /* font must be set after widget inserted in toplevel */ 54 | if (options.common_data.font) 55 | g_signal_connect_after (G_OBJECT (w), "realize", G_CALLBACK (realize_cb), NULL); 56 | 57 | return w; 58 | } 59 | 60 | void 61 | font_print_result (void) 62 | { 63 | if (options.font_data.separate_output) 64 | { 65 | PangoFontFace *face; 66 | PangoFontFamily *family; 67 | gint size; 68 | 69 | #if GTK_CHECK_VERSION(3,2,0) 70 | face = gtk_font_chooser_get_font_face (GTK_FONT_CHOOSER (font)); 71 | family = gtk_font_chooser_get_font_family (GTK_FONT_CHOOSER (font)); 72 | size = gtk_font_chooser_get_font_size (GTK_FONT_CHOOSER (font)); 73 | #else 74 | face = gtk_font_selection_get_face (GTK_FONT_SELECTION (font)); 75 | family = gtk_font_selection_get_family (GTK_FONT_SELECTION (font)); 76 | size = gtk_font_selection_get_size (GTK_FONT_SELECTION (font)); 77 | #endif 78 | 79 | if (options.common_data.quoted_output) 80 | { 81 | gchar *q1 = g_shell_quote (pango_font_family_get_name (family)); 82 | gchar *q2 = g_shell_quote (pango_font_face_get_face_name (face)); 83 | 84 | g_printf ("%s%s%s%s%d\n", q1, options.common_data.separator, q2, 85 | options.common_data.separator, size / PANGO_SCALE); 86 | 87 | g_free (q1); 88 | g_free (q2); 89 | } 90 | else 91 | { 92 | g_printf ("%s%s%s%s%d\n", pango_font_family_get_name (family), options.common_data.separator, 93 | pango_font_face_get_face_name (face), options.common_data.separator, size / PANGO_SCALE); 94 | } 95 | } 96 | else 97 | { 98 | #if GTK_CHECK_VERSION(3,2,0) 99 | gchar *fn = gtk_font_chooser_get_font (GTK_FONT_CHOOSER (font)); 100 | #else 101 | gchar *fn = gtk_font_selection_get_font_name (GTK_FONT_SELECTION (font)); 102 | #endif 103 | 104 | if (options.common_data.quoted_output) 105 | { 106 | gchar *buf = g_shell_quote (fn); 107 | g_printf ("%s\n", buf); 108 | g_free (buf); 109 | } 110 | else 111 | g_printf ("%s\n", fn); 112 | 113 | g_free (fn); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/html.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of YAD. 3 | * 4 | * YAD 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 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * YAD is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with YAD. If not, see . 16 | * 17 | * Copyright (C) 2008-2019, Victor Ananjevsky 18 | */ 19 | 20 | #include 21 | #include 22 | 23 | #include "yad.h" 24 | 25 | #ifdef USE_WEBKIT2 26 | #include 27 | #else 28 | #include 29 | #endif 30 | 31 | static WebKitWebView *view; 32 | 33 | static GString *inbuf; 34 | 35 | #ifdef USE_WEBKIT2 36 | static gboolean is_loaded = FALSE; 37 | #else 38 | static gboolean is_link = FALSE; 39 | #endif 40 | 41 | #ifndef PATH_MAX 42 | #define PATH_MAX 4096 43 | #endif 44 | 45 | static void 46 | load_uri (const gchar * uri) 47 | { 48 | gchar *addr = NULL; 49 | 50 | if (!uri || !uri[0]) 51 | return; 52 | 53 | if (g_file_test (uri, G_FILE_TEST_EXISTS)) 54 | { 55 | if (g_path_is_absolute (uri)) 56 | addr = g_filename_to_uri (uri, NULL, NULL); 57 | else 58 | { 59 | gchar *afn = g_new0 (gchar, PATH_MAX); 60 | realpath (uri, afn); 61 | addr = g_filename_to_uri (afn, NULL, NULL); 62 | g_free (afn); 63 | } 64 | } 65 | else 66 | { 67 | if (g_uri_parse_scheme (uri) == NULL) 68 | addr = g_strdup_printf ("https://%s", uri); 69 | else 70 | addr = g_strdup (uri); 71 | } 72 | 73 | if (addr) 74 | { 75 | webkit_web_view_load_uri (view, addr); 76 | g_free (addr); 77 | } 78 | else 79 | g_printerr ("yad_html_load_uri: cannot load uri '%s'\n", uri); 80 | } 81 | 82 | #ifndef USE_WEBKIT2 83 | 84 | static gboolean 85 | link_cb (WebKitWebView * v, WebKitWebFrame * f, WebKitNetworkRequest * r, 86 | WebKitWebNavigationAction * act, WebKitWebPolicyDecision * pd, gpointer d) 87 | { 88 | gchar *uri; 89 | 90 | if (webkit_web_navigation_action_get_reason (act) != WEBKIT_WEB_NAVIGATION_REASON_LINK_CLICKED) 91 | { 92 | /* skip handling non clicked reasons */ 93 | webkit_web_policy_decision_use (pd); 94 | return TRUE; 95 | } 96 | 97 | uri = (gchar *) webkit_network_request_get_uri (r); 98 | 99 | if (!options.html_data.browser) 100 | { 101 | if (options.html_data.print_uri) 102 | g_printf ("%s\n", uri); 103 | else 104 | { 105 | gchar *cmd = g_strdup_printf (settings.open_cmd, uri); 106 | g_spawn_command_line_async (cmd, NULL); 107 | g_free (cmd); 108 | } 109 | webkit_web_policy_decision_ignore (pd); 110 | } 111 | else 112 | { 113 | if (options.html_data.uri_cmd) 114 | { 115 | gint ret = -1; 116 | gchar *cmd = g_strdup_printf (options.html_data.uri_cmd, uri); 117 | static gchar *vb = NULL, *vm = NULL; 118 | 119 | /* set environment */ 120 | g_free (vb); 121 | vb = g_strdup_printf ("%d", webkit_web_navigation_action_get_button (act)); 122 | g_setenv ("YAD_HTML_BUTTON", vb, TRUE); 123 | g_free (vm); 124 | vm = g_strdup_printf ("%d", webkit_web_navigation_action_get_modifier_state (act)); 125 | g_setenv ("YAD_HTML_KEYS", vm, TRUE); 126 | 127 | /* run handler */ 128 | ret = run_command_sync (cmd, NULL, NULL); 129 | /* actual exit code in highest byte */ 130 | switch (ret >> 8) 131 | { 132 | case 0: 133 | webkit_web_policy_decision_use (pd); 134 | break; 135 | case 1: 136 | webkit_web_policy_decision_ignore (pd); 137 | break; 138 | case 2: 139 | webkit_web_policy_decision_download (pd); 140 | break; 141 | default: 142 | g_printerr ("yad: undefined return code (%d) from uri handler\n", ret >> 8); 143 | webkit_web_policy_decision_ignore (pd); 144 | break; 145 | } 146 | g_free (cmd); 147 | } 148 | else 149 | webkit_web_policy_decision_use (pd); 150 | } 151 | 152 | return TRUE; 153 | } 154 | 155 | static void 156 | link_hover_cb (WebKitWebView * v, const gchar * t, const gchar * link, gpointer * d) 157 | { 158 | is_link = (link != NULL); 159 | } 160 | 161 | #else 162 | 163 | static void 164 | loaded_cb (WebKitWebView *v, WebKitLoadEvent ev, gpointer d) 165 | { 166 | if (ev == WEBKIT_LOAD_FINISHED) 167 | is_loaded = TRUE; 168 | } 169 | 170 | static gboolean 171 | policy_cb (WebKitWebView *v, WebKitPolicyDecision *pd, WebKitPolicyDecisionType pt, gpointer d) 172 | { 173 | if (is_loaded && !options.html_data.browser) 174 | { 175 | WebKitNavigationAction *act = webkit_navigation_policy_decision_get_navigation_action (WEBKIT_NAVIGATION_POLICY_DECISION (pd)); 176 | webkit_policy_decision_ignore (pd); 177 | if (webkit_navigation_action_get_navigation_type (act) == WEBKIT_NAVIGATION_TYPE_LINK_CLICKED) 178 | { 179 | WebKitURIRequest *r = webkit_navigation_action_get_request (act); 180 | gchar *uri = (gchar *) webkit_uri_request_get_uri (r); 181 | 182 | if (options.html_data.print_uri) 183 | g_printf ("%s\n", uri); 184 | else 185 | g_app_info_launch_default_for_uri (uri, NULL, NULL); 186 | } 187 | } 188 | else 189 | return FALSE; 190 | 191 | return TRUE; 192 | } 193 | 194 | #endif 195 | 196 | static void 197 | select_file_cb (GtkEntry * entry, GtkEntryIconPosition pos, GdkEventButton * ev, gpointer d) 198 | { 199 | GtkWidget *dlg; 200 | static gchar *dir = NULL; 201 | 202 | if (ev->button != 1 || pos != GTK_ENTRY_ICON_SECONDARY) 203 | return; 204 | 205 | dlg = gtk_file_chooser_dialog_new (_("YAD - Select File"), 206 | GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (entry))), 207 | GTK_FILE_CHOOSER_ACTION_OPEN, 208 | GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL); 209 | if (dir) 210 | gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dlg), dir); 211 | 212 | if (gtk_dialog_run (GTK_DIALOG (dlg)) == GTK_RESPONSE_ACCEPT) 213 | { 214 | gchar *uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dlg)); 215 | gtk_entry_set_text (entry, uri); 216 | g_free (uri); 217 | 218 | /* keep current dir */ 219 | g_free (dir); 220 | dir = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dlg)); 221 | } 222 | 223 | gtk_widget_destroy (dlg); 224 | } 225 | 226 | static void 227 | do_open_cb (GtkWidget * w, GtkDialog * dlg) 228 | { 229 | gtk_dialog_response (dlg, GTK_RESPONSE_ACCEPT); 230 | } 231 | 232 | static void 233 | open_cb (GtkWidget * w, gpointer d) 234 | { 235 | GtkWidget *dlg, *cnt, *lbl, *entry; 236 | 237 | dlg = gtk_dialog_new_with_buttons (_("Open URI"), 238 | GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view))), 239 | GTK_DIALOG_DESTROY_WITH_PARENT, 240 | GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); 241 | gtk_window_set_default_size (GTK_WINDOW (dlg), 350, -1); 242 | 243 | cnt = gtk_dialog_get_content_area (GTK_DIALOG (dlg)); 244 | 245 | lbl = gtk_label_new (_("Enter URI or file name:")); 246 | #if !GTK_CHECK_VERSION(3,0,0) 247 | gtk_misc_set_alignment (GTK_MISC (lbl), 0.0, 0.5); 248 | #else 249 | gtk_label_set_xalign (GTK_LABEL (lbl), 0.0); 250 | #endif 251 | gtk_widget_show (lbl); 252 | gtk_box_pack_start (GTK_BOX (cnt), lbl, TRUE, FALSE, 2); 253 | 254 | entry = gtk_entry_new (); 255 | gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY, "document-open"); 256 | gtk_widget_show (entry); 257 | gtk_box_pack_start (GTK_BOX (cnt), entry, TRUE, FALSE, 2); 258 | 259 | g_signal_connect (G_OBJECT (entry), "icon-press", G_CALLBACK (select_file_cb), NULL); 260 | g_signal_connect (G_OBJECT (entry), "activate", G_CALLBACK (do_open_cb), dlg); 261 | 262 | if (gtk_dialog_run (GTK_DIALOG (dlg)) == GTK_RESPONSE_ACCEPT) 263 | load_uri (gtk_entry_get_text (GTK_ENTRY (entry))); 264 | 265 | gtk_widget_destroy (dlg); 266 | } 267 | 268 | static gboolean 269 | menu_cb (WebKitWebView * view, GtkWidget * menu, WebKitHitTestResult * hit, gboolean kb, gpointer d) 270 | { 271 | GtkWidget *mi; 272 | 273 | #ifndef USE_WEBKIT2 274 | if (!is_link) 275 | { 276 | /* add open item */ 277 | mi = gtk_separator_menu_item_new (); 278 | gtk_widget_show (mi); 279 | gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), mi); 280 | 281 | mi = gtk_image_menu_item_new_from_stock ("gtk-open", NULL); 282 | gtk_widget_show (mi); 283 | gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), mi); 284 | g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (open_cb), NULL); 285 | 286 | /* add quit item */ 287 | mi = gtk_separator_menu_item_new (); 288 | gtk_widget_show (mi); 289 | gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi); 290 | 291 | mi = gtk_image_menu_item_new_from_stock ("gtk-quit", NULL); 292 | gtk_widget_show (mi); 293 | gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi); 294 | g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (gtk_main_quit), NULL); 295 | } 296 | #endif 297 | 298 | return FALSE; 299 | } 300 | 301 | static void 302 | title_cb (GObject *obj, GParamSpec *spec, GtkWindow *dlg) 303 | { 304 | const gchar *title = webkit_web_view_get_title (view); 305 | if (title) 306 | gtk_window_set_title (dlg, title); 307 | } 308 | 309 | static void 310 | icon_cb (GObject *obj, GParamSpec *spec, GtkWindow *dlg) 311 | { 312 | #ifdef USE_WEBKIT2 313 | GdkPixbuf *pb = gdk_pixbuf_get_from_surface (webkit_web_view_get_favicon (view), 0, 0, -1, -1); 314 | #else 315 | GdkPixbuf *pb = webkit_web_view_try_get_favicon_pixbuf (view, 16, 16); 316 | #endif 317 | if (pb) 318 | { 319 | gtk_window_set_icon (dlg, pb); 320 | g_object_unref (pb); 321 | } 322 | } 323 | 324 | static gboolean 325 | handle_stdin (GIOChannel * ch, GIOCondition cond, gpointer d) 326 | { 327 | gchar *buf; 328 | #ifdef USE_WEBKIT2 329 | GBytes *data; 330 | #endif 331 | GError *err = NULL; 332 | 333 | switch (g_io_channel_read_line (ch, &buf, NULL, NULL, &err)) 334 | { 335 | case G_IO_STATUS_NORMAL: 336 | g_string_append (inbuf, buf); 337 | return TRUE; 338 | 339 | case G_IO_STATUS_ERROR: 340 | g_printerr ("yad_html_handle_stdin(): %s\n", err->message); 341 | g_error_free (err); 342 | return FALSE; 343 | 344 | case G_IO_STATUS_EOF: 345 | #ifdef USE_WEBKIT2 346 | data = g_bytes_new (inbuf->str, inbuf->len); 347 | /*g_string_free (inbuf, TRUE); */ /* FIXME: IS THAT NEEDED ??? (and where) */ 348 | webkit_web_view_load_bytes (view, data, options.html_data.mime, options.html_data.encoding, NULL); 349 | g_bytes_unref (data); 350 | #else 351 | webkit_web_view_load_string (view, inbuf->str, options.html_data.mime, options.html_data.encoding, NULL); 352 | #endif 353 | return FALSE; 354 | 355 | case G_IO_STATUS_AGAIN: 356 | return TRUE; 357 | } 358 | 359 | return FALSE; 360 | } 361 | 362 | GtkWidget * 363 | html_create_widget (GtkWidget * dlg) 364 | { 365 | GtkWidget *sw; 366 | #ifdef USE_WEBKIT2 367 | WebKitSettings *settings; 368 | #else 369 | WebKitWebSettings *settings; 370 | #endif 371 | SoupSession *sess; 372 | 373 | sw = gtk_scrolled_window_new (NULL, NULL); 374 | gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), options.hscroll_policy, options.vscroll_policy); 375 | 376 | view = WEBKIT_WEB_VIEW (webkit_web_view_new ()); 377 | gtk_container_add (GTK_CONTAINER (sw), GTK_WIDGET (view)); 378 | 379 | #ifdef USE_WEBKIT2 380 | settings = webkit_settings_new (); 381 | #else 382 | settings = webkit_web_settings_new (); 383 | #endif 384 | 385 | g_object_set (G_OBJECT (settings), "user-agent", options.html_data.user_agent, NULL); 386 | if (options.html_data.user_style) 387 | { 388 | gchar *uri = g_filename_to_uri (options.html_data.user_style, NULL, NULL); 389 | g_object_set (G_OBJECT (settings), "user-stylesheet-uri", uri, NULL); 390 | } 391 | webkit_web_view_set_settings (view, settings); 392 | 393 | #ifdef USE_WEBKIT2 394 | webkit_settings_set_default_charset (settings, g_get_codeset ()); 395 | 396 | g_signal_connect (view, "decide-policy", G_CALLBACK (policy_cb), NULL); 397 | #else 398 | g_object_set (G_OBJECT (settings), "default-encoding", g_get_codeset (), NULL); 399 | 400 | g_signal_connect (view, "hovering-over-link", G_CALLBACK (link_hover_cb), NULL); 401 | g_signal_connect (view, "navigation-policy-decision-requested", G_CALLBACK (link_cb), NULL); 402 | #endif 403 | 404 | if (options.html_data.browser) 405 | { 406 | g_signal_connect (view, "context-menu", G_CALLBACK (menu_cb), NULL); 407 | if (!options.data.dialog_title) 408 | g_signal_connect (view, "notify::title", G_CALLBACK (title_cb), dlg); 409 | if (strcmp (options.data.window_icon, "yad") == 0) 410 | #ifdef USE_WEBKIT2 411 | g_signal_connect (view, "notify::favicon", G_CALLBACK (icon_cb), dlg); 412 | #else 413 | g_signal_connect (view, "icon-loaded", G_CALLBACK (icon_cb), dlg); 414 | #endif 415 | } 416 | #ifdef USE_WEBKIT2 417 | else 418 | { 419 | g_object_set (G_OBJECT(settings), "enable-caret-browsing", FALSE, NULL); 420 | g_object_set (G_OBJECT(settings), "enable-developer-extras", FALSE, NULL); 421 | g_object_set (G_OBJECT(settings), "enable-html5-database", FALSE, NULL); 422 | g_object_set (G_OBJECT(settings), "enable-html5-local-storage", FALSE, NULL); 423 | g_object_set (G_OBJECT(settings), "enable-offline-web-application-cache", FALSE, NULL); 424 | g_object_set (G_OBJECT(settings), "enable-page-cache", FALSE, NULL); 425 | g_object_set (G_OBJECT(settings), "enable-plugins", FALSE, NULL); 426 | g_object_set (G_OBJECT (settings), "enable-private-browsing", TRUE, NULL); 427 | g_signal_connect (view, "load-changed", G_CALLBACK (loaded_cb), NULL); 428 | } 429 | #endif 430 | 431 | #ifndef USE_WEBKIT2 432 | sess = webkit_get_default_session (); 433 | soup_session_add_feature_by_type (sess, SOUP_TYPE_PROXY_RESOLVER_DEFAULT); 434 | g_object_set (G_OBJECT (sess), SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE, NULL); 435 | #endif 436 | 437 | gtk_widget_show_all (sw); 438 | gtk_widget_grab_focus (GTK_WIDGET (view)); 439 | 440 | if (options.html_data.uri) 441 | load_uri (options.html_data.uri); 442 | else if (!options.html_data.browser) 443 | { 444 | GIOChannel *ch; 445 | 446 | inbuf = g_string_new (NULL); 447 | ch = g_io_channel_unix_new (0); 448 | g_io_channel_set_encoding (ch, NULL, NULL); 449 | g_io_channel_set_flags (ch, G_IO_FLAG_NONBLOCK, NULL); 450 | g_io_add_watch (ch, G_IO_IN | G_IO_HUP, handle_stdin, NULL); 451 | } 452 | else if (options.extra_data) 453 | load_uri (options.extra_data[0]); 454 | 455 | return sw; 456 | } 457 | -------------------------------------------------------------------------------- /src/meson.build: -------------------------------------------------------------------------------- 1 | src = [ 2 | 'about.c', 3 | 'calendar.c', 4 | 'color.c', 5 | 'cpicker.c', 6 | 'dnd.c', 7 | 'entry.c', 8 | 'file.c', 9 | 'font.c', 10 | 'form.c', 11 | 'icons.c', 12 | 'list.c', 13 | 'main.c', 14 | 'notebook.c', 15 | 'notification.c', 16 | 'option.c', 17 | 'paned.c', 18 | 'picture.c', 19 | 'print.c', 20 | 'progress.c', 21 | 'scale.c', 22 | 'text.c', 23 | 'util.c', 24 | ] 25 | 26 | cfg = configuration_data() 27 | 28 | cfg.set_quoted('PACKAGE_NAME', meson.project_name()) 29 | cfg.set_quoted('PACKAGE_VERSION', meson.project_version()) 30 | cfg.set_quoted('PACKAGE_URL', 'http://github.com/step-/yad') 31 | cfg.set_quoted('RGB_FILE', get_option('rgb')) 32 | cfg.set('HAVE_TRAY', 1) 33 | 34 | dep = [ 35 | meson.get_compiler('c').find_library('m'), 36 | dependency('gtk+-3.0'), 37 | dependency('gtk+-unix-print-3.0'), 38 | ] 39 | 40 | gtk_layer_shell = dependency('gtk-layer-shell-0', required: false) 41 | if gtk_layer_shell.found() 42 | dep += gtk_layer_shell 43 | cfg.set('HAVE_GTK_LAYER_SHELL', 1) 44 | endif 45 | 46 | configure_file( 47 | output : 'config.h', 48 | configuration : cfg, 49 | ) 50 | 51 | yad = executable( 52 | 'yad', 53 | src, 54 | dependencies: dep, 55 | install: true, 56 | ) 57 | -------------------------------------------------------------------------------- /src/notebook.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of YAD. 3 | * 4 | * YAD 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 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * YAD is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with YAD. If not, see . 16 | * 17 | * Copyright (C) 2008-2019, Victor Ananjevsky 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include "yad.h" 35 | 36 | static GtkWidget *notebook; 37 | 38 | GtkWidget * 39 | notebook_create_widget (GtkWidget * dlg) 40 | { 41 | GtkWidget *w; 42 | GSList *tab; 43 | 44 | /* get shared memory */ 45 | tabs = get_tabs (options.common_data.key, TRUE); 46 | if (!tabs) 47 | exit (-1); 48 | 49 | /* create widget */ 50 | w = notebook = gtk_notebook_new (); 51 | gtk_widget_set_name (w, "yad-notebook-widget"); 52 | gtk_notebook_set_tab_pos (GTK_NOTEBOOK (w), options.notebook_data.pos); 53 | gtk_container_set_border_width (GTK_CONTAINER (w), 5); 54 | 55 | /* add tabs */ 56 | for (tab = options.notebook_data.tabs; tab; tab = tab->next) 57 | { 58 | GtkWidget *a, *s; 59 | 60 | SETUNDEPR (a, gtk_alignment_new, 0.5, 0.5, 1, 1); 61 | UNDEPR (gtk_alignment_set_padding, GTK_ALIGNMENT (a), 62 | options.notebook_data.borders, options.notebook_data.borders, 63 | options.notebook_data.borders, options.notebook_data.borders); 64 | 65 | s = gtk_socket_new (); 66 | gtk_container_add (GTK_CONTAINER (a), s); 67 | g_object_set_data (G_OBJECT (a), "socket", s); 68 | 69 | gtk_notebook_append_page (GTK_NOTEBOOK (w), a, get_label ((gchar *) tab->data, 0, s)); 70 | gtk_container_child_set( GTK_CONTAINER (w), a, "tab-expand", options.notebook_data.expand, NULL); 71 | } 72 | 73 | return w; 74 | } 75 | 76 | void 77 | notebook_swallow_childs (void) 78 | { 79 | guint i, n_tabs; 80 | gboolean all_registered; 81 | 82 | n_tabs = g_slist_length (options.notebook_data.tabs); 83 | 84 | /* wait until all children are registered */ 85 | do 86 | { 87 | all_registered = TRUE; 88 | for (i = 1; i <= n_tabs; i++) 89 | if (!tabs[i].xid) 90 | { 91 | all_registered = FALSE; 92 | break; 93 | } 94 | if (!all_registered) 95 | usleep (1000); 96 | } 97 | while (!all_registered); 98 | 99 | for (i = 1; i <= n_tabs; i++) 100 | { 101 | GtkWidget *s = 102 | GTK_WIDGET (g_object_get_data 103 | (G_OBJECT (gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), i - 1)), "socket")); 104 | 105 | if (tabs[i].pid != -1) 106 | gtk_socket_add_id (GTK_SOCKET (s), tabs[i].xid); 107 | } 108 | 109 | /* set active tab */ 110 | if (options.notebook_data.active > 0) 111 | gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), options.notebook_data.active - 1); 112 | } 113 | 114 | void 115 | notebook_print_result (void) 116 | { 117 | guint i, n_tabs; 118 | 119 | n_tabs = g_slist_length (options.notebook_data.tabs); 120 | for (i = 1; i <= n_tabs; i++) 121 | { 122 | if (tabs[i].pid != -1) 123 | kill (tabs[i].pid, SIGUSR1); 124 | } 125 | } 126 | 127 | void 128 | notebook_close_childs (void) 129 | { 130 | guint i, n_tabs, signal, count; 131 | struct shmid_ds buf; 132 | gboolean is_running; 133 | 134 | n_tabs = g_slist_length (options.notebook_data.tabs); 135 | for (i = 1; i <= n_tabs; i++) 136 | { 137 | if (tabs[i].pid != -1) 138 | kill (tabs[i].pid, SIGUSR2); 139 | else 140 | break; 141 | } 142 | 143 | /* counted wait for subprocesses to exit */ 144 | signal = count = 0; 145 | do 146 | { 147 | is_running = FALSE; 148 | for (i = 1; i <= n_tabs; i++) 149 | { 150 | if (tabs[i].pid != -1 && kill (tabs[i].pid, signal) == 0) 151 | { 152 | is_running = TRUE; 153 | break; 154 | } 155 | } 156 | 157 | if (is_running) 158 | { 159 | usleep (1000); 160 | /* force subprocesses to exit after 10 s timeout */ 161 | if (++count > 10000) 162 | signal = SIGTERM; 163 | } 164 | } 165 | while (is_running); 166 | 167 | /* cleanup shared memory */ 168 | shmctl (tabs[0].pid, IPC_RMID, &buf); 169 | shmdt (tabs); 170 | } 171 | -------------------------------------------------------------------------------- /src/notification.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of YAD. 3 | * 4 | * YAD 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 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * YAD is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with YAD. If not, see . 16 | * 17 | * Copyright (C) 2008-2019, Victor Ananjevsky 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "yad.h" 27 | 28 | typedef struct { 29 | gchar *name; 30 | gchar *action; 31 | gchar *icon; 32 | } MenuData; 33 | 34 | static GtkStatusIcon *status_icon; 35 | 36 | static gchar *icon = NULL; 37 | static gchar *action = NULL; 38 | 39 | static GSList *menu_data = NULL; 40 | 41 | static gint exit_code; 42 | 43 | static void popup_menu_cb (GtkStatusIcon *, guint, guint, gpointer); 44 | 45 | static void 46 | free_menu_data (gpointer data) 47 | { 48 | MenuData *m = (MenuData *) data; 49 | 50 | if (m) { 51 | g_free (m->name); 52 | g_free (m->action); 53 | g_free (m->icon); 54 | g_free (m); 55 | } 56 | } 57 | 58 | static void 59 | parse_menu_str (gchar * str) 60 | { 61 | gchar **menu_vals; 62 | gint i = 0; 63 | 64 | if (menu_data) 65 | { 66 | g_slist_free_full (menu_data, free_menu_data); 67 | menu_data = NULL; 68 | } 69 | 70 | menu_vals = g_strsplit (str, options.common_data.separator, -1); 71 | 72 | while (menu_vals[i] != NULL) 73 | { 74 | MenuData *mdata = g_new0 (MenuData, 1); 75 | gchar **s = g_strsplit (menu_vals[i], options.common_data.item_separator, 3); 76 | 77 | if (s[0]) 78 | { 79 | mdata->name = g_strdup (s[0]); 80 | if (s[1]) 81 | { 82 | mdata->action = g_strdup (s[1]); 83 | if (s[2]) 84 | mdata->icon = g_strdup (s[2]); 85 | } 86 | } 87 | menu_data = g_slist_append (menu_data, mdata); 88 | g_strfreev (s); 89 | i++; 90 | } 91 | 92 | g_strfreev (menu_vals); 93 | } 94 | 95 | static void 96 | timeout_cb (gpointer data) 97 | { 98 | exit_code = YAD_RESPONSE_TIMEOUT; 99 | gtk_main_quit (); 100 | } 101 | 102 | static void 103 | set_icon (void) 104 | { 105 | GdkPixbuf *pixbuf = NULL; 106 | GError *err = NULL; 107 | gboolean b; 108 | GtkStockItem sit; 109 | if (icon == NULL || *icon == '\0') 110 | { 111 | UNDEPR (gtk_status_icon_set_from_icon_name, status_icon, "yad"); 112 | return; 113 | } 114 | 115 | SETUNDEPR (b, gtk_stock_lookup, icon, &sit); 116 | if (b) 117 | { 118 | static GtkWidget *button = NULL; 119 | if (button == NULL) 120 | button = gtk_button_new (); 121 | 122 | SETUNDEPR (pixbuf, gtk_widget_render_icon, button, sit.stock_id, GTK_ICON_SIZE_SMALL_TOOLBAR, ""); 123 | } 124 | else if (g_file_test (icon, G_FILE_TEST_EXISTS)) 125 | { 126 | gint isize = (options.common_data.icon_size > 0) ? options.common_data.icon_size : 16; 127 | 128 | pixbuf = gdk_pixbuf_new_from_file_at_scale (icon, isize, isize, TRUE, &err); 129 | if (err) 130 | { 131 | g_printerr (_("Could not load notification icon '%s': %s\n"), icon, err->message); 132 | g_clear_error (&err); 133 | } 134 | } 135 | else 136 | UNDEPR (gtk_status_icon_set_from_icon_name, status_icon, icon); 137 | if (pixbuf) 138 | { 139 | UNDEPR (gtk_status_icon_set_from_pixbuf, status_icon, pixbuf); 140 | g_object_unref (pixbuf); 141 | } 142 | } 143 | 144 | static gboolean 145 | activate_cb (GtkWidget * widget, YadData * data) 146 | { 147 | if ((action == NULL && !options.common_data.listen) || (action && g_ascii_strcasecmp (action, "quit") == 0)) 148 | { 149 | exit_code = YAD_RESPONSE_OK; 150 | gtk_main_quit (); 151 | } 152 | else if (action) 153 | { 154 | if (g_ascii_strcasecmp (action, "menu") == 0) 155 | popup_menu_cb (GTK_STATUS_ICON (widget), 1, GDK_CURRENT_TIME, data); 156 | else 157 | run_command_async (action); 158 | } 159 | 160 | return TRUE; 161 | } 162 | 163 | static gboolean 164 | middle_quit_cb (GtkStatusIcon * icon, GdkEventButton * ev, gpointer data) 165 | { 166 | if (ev->button == 2) 167 | { 168 | if (options.data.escape_ok) 169 | exit_code = YAD_RESPONSE_OK; 170 | else 171 | exit_code = YAD_RESPONSE_ESC; 172 | gtk_main_quit (); 173 | } 174 | 175 | return FALSE; 176 | } 177 | 178 | static void 179 | popup_menu_item_activate_cb (GtkWidget * w, gpointer data) 180 | { 181 | gchar *cmd = (gchar *) data; 182 | 183 | if (cmd) 184 | { 185 | if (g_ascii_strcasecmp (g_strstrip (cmd), "quit") == 0) 186 | { 187 | exit_code = YAD_RESPONSE_OK; 188 | gtk_main_quit (); 189 | } 190 | else 191 | run_command_async (cmd); 192 | } 193 | } 194 | 195 | static void 196 | popup_menu_cb (GtkStatusIcon *icon, guint button, guint activate_time, gpointer data) 197 | { 198 | GtkWidget *menu; 199 | GtkWidget *item; 200 | GSList *m; 201 | 202 | if (!menu_data) 203 | return; 204 | 205 | menu = gtk_menu_new (); 206 | gtk_menu_set_reserve_toggle_size (GTK_MENU (menu), FALSE); 207 | 208 | for (m = menu_data; m; m = m->next) 209 | { 210 | MenuData *d = (MenuData *) m->data; 211 | GtkStockItem it; 212 | gboolean b; 213 | 214 | if (d->name) 215 | { 216 | if (d->icon) 217 | { 218 | SETUNDEPR (b, gtk_stock_lookup, d->icon, &it); 219 | if (b) 220 | { 221 | SETUNDEPR (item, gtk_image_menu_item_new_from_stock, d->icon, NULL); 222 | gtk_menu_item_set_label (GTK_MENU_ITEM (item), d->name); 223 | } 224 | else 225 | { 226 | GdkPixbuf *pb = get_pixbuf (d->icon, YAD_SMALL_ICON, TRUE); 227 | SETUNDEPR (item, gtk_image_menu_item_new_with_mnemonic, d->name); 228 | if (pb) 229 | { 230 | UNDEPR (gtk_image_menu_item_set_image, GTK_IMAGE_MENU_ITEM (item), gtk_image_new_from_pixbuf (pb)); 231 | g_object_unref (pb); 232 | } 233 | } 234 | } 235 | else 236 | { 237 | SETUNDEPR (b, gtk_stock_lookup, d->name, &it); 238 | if (b) 239 | { 240 | SETUNDEPR (item, gtk_image_menu_item_new_from_stock, d->name, NULL); 241 | } 242 | else 243 | item = gtk_menu_item_new_with_mnemonic (d->name); 244 | } 245 | g_signal_connect (GTK_MENU_ITEM (item), "activate", 246 | G_CALLBACK (popup_menu_item_activate_cb), (gpointer) d->action); 247 | } 248 | else 249 | item = gtk_separator_menu_item_new (); 250 | 251 | gtk_widget_show (item); 252 | gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); 253 | } 254 | UNDEPR (gtk_menu_popup, GTK_MENU (menu), NULL, NULL, gtk_status_icon_position_menu, icon, button, activate_time); 255 | } 256 | 257 | static gboolean 258 | handle_stdin (GIOChannel * channel, GIOCondition condition, gpointer data) 259 | { 260 | if ((condition & G_IO_IN) != 0) 261 | { 262 | GString *string; 263 | GError *err = NULL; 264 | 265 | string = g_string_new (NULL); 266 | while (channel->is_readable == FALSE) 267 | usleep (100); 268 | 269 | do 270 | { 271 | gint status; 272 | gchar *command = NULL, *value = NULL, **args; 273 | 274 | do 275 | { 276 | status = g_io_channel_read_line_string (channel, string, NULL, &err); 277 | 278 | while (gdk_events_pending ()) 279 | gtk_main_iteration (); 280 | } 281 | while (status == G_IO_STATUS_AGAIN); 282 | 283 | if (status != G_IO_STATUS_NORMAL) 284 | { 285 | if (err) 286 | { 287 | g_printerr ("yad_notification_handle_stdin(): %s\n", err->message); 288 | g_error_free (err); 289 | err = NULL; 290 | } 291 | /* stop handling but not exit */ 292 | g_io_channel_shutdown (channel, TRUE, NULL); 293 | return FALSE; 294 | } 295 | 296 | strip_new_line (string->str); 297 | if (!string->str[0]) 298 | continue; 299 | 300 | args = g_strsplit (string->str, ":", 2); 301 | command = g_strdup (args[0]); 302 | if (args[1]) 303 | value = g_strdup (args[1]); 304 | g_strfreev (args); 305 | if (value) 306 | g_strstrip (value); 307 | 308 | if (!g_ascii_strcasecmp (command, "icon") && value) 309 | { 310 | g_free (icon); 311 | icon = g_strdup (value); 312 | 313 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS; 314 | if (gtk_status_icon_get_visible (status_icon) && gtk_status_icon_is_embedded (status_icon)) 315 | set_icon (); 316 | G_GNUC_END_IGNORE_DEPRECATIONS; 317 | } 318 | else if (!g_ascii_strcasecmp (command, "tooltip")) 319 | { 320 | if (g_utf8_validate (value, -1, NULL)) 321 | { 322 | gchar *message = g_strcompress (value); 323 | if (!options.data.no_markup) 324 | { 325 | UNDEPR (gtk_status_icon_set_tooltip_markup, status_icon, message); 326 | } 327 | else 328 | { 329 | UNDEPR (gtk_status_icon_set_tooltip_text, status_icon, message); 330 | } 331 | g_free (message); 332 | } 333 | else 334 | g_printerr (_("Invalid UTF-8 in tooltip!\n")); 335 | } 336 | else if (!g_ascii_strcasecmp (command, "visible")) 337 | { 338 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS; 339 | #if !GTK_CHECK_VERSION(3,0,0) 340 | if (!g_ascii_strcasecmp (value, "blink")) 341 | { 342 | gboolean state = gtk_status_icon_get_blinking (status_icon); 343 | gtk_status_icon_set_blinking (status_icon, !state); 344 | } 345 | else 346 | #endif 347 | if (!g_ascii_strcasecmp (value, "false")) 348 | { 349 | gtk_status_icon_set_visible (status_icon, FALSE); 350 | #if !GTK_CHECK_VERSION(3,0,0) 351 | gtk_status_icon_set_blinking (status_icon, FALSE); 352 | #endif 353 | } 354 | else 355 | { 356 | gtk_status_icon_set_visible (status_icon, TRUE); 357 | #if !GTK_CHECK_VERSION(3,0,0) 358 | gtk_status_icon_set_blinking (status_icon, FALSE); 359 | #endif 360 | } 361 | G_GNUC_END_IGNORE_DEPRECATIONS; 362 | } 363 | else if (!g_ascii_strcasecmp (command, "action")) 364 | { 365 | g_free (action); 366 | if (value) 367 | action = g_strdup (value); 368 | } 369 | else if (!g_ascii_strcasecmp (command, "quit")) 370 | { 371 | exit_code = YAD_RESPONSE_OK; 372 | gtk_main_quit (); 373 | } 374 | else if (!g_ascii_strcasecmp (command, "menu")) 375 | { 376 | if (value) 377 | parse_menu_str (value); 378 | } 379 | else 380 | g_printerr (_("Unknown command '%s'\n"), command); 381 | 382 | g_free (command); 383 | g_free (value); 384 | } 385 | while (g_io_channel_get_buffer_condition (channel) == G_IO_IN); 386 | g_string_free (string, TRUE); 387 | } 388 | 389 | if ((condition & G_IO_HUP) != 0) 390 | { 391 | g_io_channel_shutdown (channel, TRUE, NULL); 392 | gtk_main_quit (); 393 | return FALSE; 394 | } 395 | 396 | return TRUE; 397 | } 398 | 399 | gint 400 | yad_notification_run () 401 | { 402 | GIOChannel *channel = NULL; 403 | 404 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS; 405 | status_icon = gtk_status_icon_new (); 406 | 407 | if (options.data.dialog_text) 408 | { 409 | if (!options.data.no_markup) 410 | gtk_status_icon_set_tooltip_markup (status_icon, options.data.dialog_text); 411 | else 412 | gtk_status_icon_set_tooltip_text (status_icon, options.data.dialog_text); 413 | } 414 | else 415 | gtk_status_icon_set_tooltip_text (status_icon, _("Yad notification")); 416 | G_GNUC_END_IGNORE_DEPRECATIONS; 417 | 418 | if (options.data.dialog_image) 419 | icon = g_strdup (options.data.dialog_image); 420 | if (options.common_data.command) 421 | action = g_strdup (options.common_data.command); 422 | 423 | set_icon (); 424 | 425 | g_signal_connect (status_icon, "activate", G_CALLBACK (activate_cb), NULL); 426 | g_signal_connect (status_icon, "popup_menu", G_CALLBACK (popup_menu_cb), NULL); 427 | 428 | if (options.notification_data.menu) 429 | parse_menu_str (options.notification_data.menu); 430 | 431 | /* quit on middle click (like press Esc) */ 432 | if (options.notification_data.middle) 433 | g_signal_connect (status_icon, "button-press-event", G_CALLBACK (middle_quit_cb), NULL); 434 | 435 | if (options.common_data.listen) 436 | { 437 | channel = g_io_channel_unix_new (0); 438 | if (channel) 439 | { 440 | g_io_channel_set_encoding (channel, NULL, NULL); 441 | g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL); 442 | g_io_add_watch (channel, G_IO_IN | G_IO_HUP, handle_stdin, NULL); 443 | } 444 | } 445 | 446 | /* Show icon and wait */ 447 | UNDEPR (gtk_status_icon_set_visible, status_icon, !options.notification_data.hidden); 448 | 449 | if (options.data.timeout > 0) 450 | g_timeout_add_seconds (options.data.timeout, (GSourceFunc) timeout_cb, NULL); 451 | 452 | gtk_main (); 453 | 454 | return exit_code; 455 | } 456 | -------------------------------------------------------------------------------- /src/paned.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of YAD. 3 | * 4 | * YAD 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 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * YAD is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with YAD. If not, see . 16 | * 17 | * Copyright (C) 2008-2019, Victor Ananjevsky 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include "yad.h" 35 | 36 | static GtkWidget *paned; 37 | 38 | GtkWidget * 39 | paned_create_widget (GtkWidget * dlg) 40 | { 41 | GtkWidget *w, *s; 42 | 43 | /* get shared memory */ 44 | tabs = get_tabs (options.common_data.key, TRUE); 45 | if (!tabs) 46 | exit (-1); 47 | 48 | /* create widget */ 49 | #if !GTK_CHECK_VERSION(3,0,0) 50 | if (options.paned_data.orient == GTK_ORIENTATION_HORIZONTAL) 51 | paned = w = gtk_hpaned_new (); 52 | else 53 | paned = w = gtk_vpaned_new (); 54 | #else 55 | paned = w = gtk_paned_new (options.paned_data.orient); 56 | #endif 57 | gtk_widget_set_name (w, "yad-paned-widget"); 58 | 59 | gtk_paned_set_position (GTK_PANED (w), options.paned_data.splitter); 60 | 61 | s = gtk_socket_new (); 62 | gtk_paned_add1 (GTK_PANED (w), s); 63 | g_object_set_data (G_OBJECT (w), "s1", s); 64 | 65 | s = gtk_socket_new (); 66 | gtk_paned_add2 (GTK_PANED (w), s); 67 | g_object_set_data (G_OBJECT (w), "s2", s); 68 | 69 | return w; 70 | } 71 | 72 | void 73 | paned_swallow_childs (void) 74 | { 75 | GtkWidget *s1, *s2; 76 | 77 | s1 = GTK_WIDGET (g_object_get_data (G_OBJECT (paned), "s1")); 78 | s2 = GTK_WIDGET (g_object_get_data (G_OBJECT (paned), "s2")); 79 | 80 | /* wait until all children are registered */ 81 | while (!tabs[1].xid || !tabs[2].xid) 82 | usleep (1000); 83 | 84 | if (tabs[1].pid != -1) 85 | gtk_socket_add_id (GTK_SOCKET (s1), tabs[1].xid); 86 | if (tabs[2].pid != -1) 87 | gtk_socket_add_id (GTK_SOCKET (s2), tabs[2].xid); 88 | } 89 | 90 | void 91 | paned_print_result (void) 92 | { 93 | if (tabs[1].pid != -1) 94 | kill (tabs[1].pid, SIGUSR1); 95 | if (tabs[2].pid != -1) 96 | kill (tabs[2].pid, SIGUSR1); 97 | } 98 | 99 | void 100 | paned_close_childs (void) 101 | { 102 | guint i; 103 | struct shmid_ds buf; 104 | gboolean is_running = TRUE; 105 | 106 | if (tabs[1].pid != -1) 107 | kill (tabs[1].pid, SIGUSR2); 108 | if (tabs[2].pid != -1) 109 | kill (tabs[2].pid, SIGUSR2); 110 | 111 | /* wait for stop subprocesses */ 112 | while (is_running) 113 | { 114 | is_running = FALSE; 115 | for (i = 1; i < 3; i++) 116 | { 117 | if (tabs[i].pid != -1 && kill (tabs[i].pid, 0) == 0) 118 | { 119 | is_running = TRUE; 120 | break; 121 | } 122 | } 123 | if (is_running) 124 | usleep (1000); 125 | } 126 | 127 | /* cleanup shared memory */ 128 | shmctl (tabs[0].pid, IPC_RMID, &buf); 129 | shmdt (tabs); 130 | } 131 | -------------------------------------------------------------------------------- /src/picture.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of YAD. 3 | * 4 | * YAD 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 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * YAD is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with YAD. If not, see . 16 | * 17 | * Copyright (C) 2008-2019, Victor Ananjevsky 18 | */ 19 | 20 | #include "yad.h" 21 | 22 | static GtkWidget *picture; 23 | static GtkWidget *viewport; 24 | static GtkWidget *popup_menu; 25 | 26 | static GdkPixbufAnimation *anim_pb; 27 | static GdkPixbuf *orig_pb; 28 | 29 | static gboolean loaded = FALSE; 30 | static gboolean animated = FALSE; 31 | 32 | enum { 33 | SIZE_FIT, 34 | SIZE_ORIG, 35 | SIZE_INC, 36 | SIZE_DEC 37 | }; 38 | 39 | enum { 40 | ROTATE_LEFT, 41 | ROTATE_RIGHT, 42 | ROTATE_FLIP_VERT, 43 | ROTATE_FLIP_HOR 44 | }; 45 | 46 | static void 47 | load_picture (gchar *filename) 48 | { 49 | anim_pb = gdk_pixbuf_animation_new_from_file (filename, NULL); 50 | orig_pb = gdk_pixbuf_animation_get_static_image (anim_pb); 51 | 52 | if (orig_pb) 53 | { 54 | if (gdk_pixbuf_animation_is_static_image (anim_pb)) 55 | gtk_image_set_from_pixbuf (GTK_IMAGE (picture), orig_pb); 56 | else 57 | { 58 | gtk_image_set_from_animation (GTK_IMAGE (picture), anim_pb); 59 | animated = TRUE; 60 | } 61 | loaded = TRUE; 62 | } 63 | else 64 | gtk_image_set_from_icon_name (GTK_IMAGE (picture), "image-missing", GTK_ICON_SIZE_DIALOG); 65 | } 66 | 67 | void 68 | picture_fit_to_window () 69 | { 70 | gdouble width, height, ww, wh; 71 | gdouble factor; 72 | 73 | if (animated) 74 | return; 75 | 76 | width = gdk_pixbuf_get_width (orig_pb); 77 | height = gdk_pixbuf_get_height (orig_pb); 78 | 79 | ww = gdk_window_get_width (gtk_viewport_get_view_window (GTK_VIEWPORT (viewport))); 80 | wh = gdk_window_get_height (gtk_viewport_get_view_window (GTK_VIEWPORT (viewport))); 81 | 82 | factor = MIN (ww / width, wh / height); 83 | if (factor < 1.0) 84 | { 85 | GdkPixbuf *pb = gdk_pixbuf_scale_simple (g_object_ref (orig_pb), width * factor, height * factor, GDK_INTERP_HYPER); 86 | if (pb) 87 | { 88 | GdkPixbuf *old_pb = gtk_image_get_pixbuf (GTK_IMAGE (picture)); 89 | gtk_image_set_from_pixbuf (GTK_IMAGE (picture), pb); 90 | g_object_unref (old_pb); 91 | } 92 | } 93 | } 94 | 95 | static void 96 | change_size_cb (GtkWidget *w, gint type) 97 | { 98 | gdouble width, height; 99 | GdkPixbuf *new_pb, *pb = gtk_image_get_pixbuf (GTK_IMAGE (picture)); 100 | 101 | if (!pb) 102 | { 103 | g_printerr ("picture: can't get pixbuf\n"); 104 | return; 105 | } 106 | 107 | width = gdk_pixbuf_get_width (pb); 108 | height = gdk_pixbuf_get_height (pb); 109 | 110 | switch (type) 111 | { 112 | case SIZE_FIT: 113 | picture_fit_to_window (); 114 | break; 115 | case SIZE_ORIG: 116 | gtk_image_set_from_pixbuf (GTK_IMAGE (picture), orig_pb); 117 | g_object_unref (pb); 118 | break; 119 | case SIZE_INC: 120 | new_pb = gdk_pixbuf_scale_simple (pb, width + options.picture_data.inc, 121 | height + options.picture_data.inc, GDK_INTERP_HYPER); 122 | if (new_pb) 123 | { 124 | gtk_image_set_from_pixbuf (GTK_IMAGE (picture), new_pb); 125 | g_object_unref (pb); 126 | } 127 | break; 128 | case SIZE_DEC: 129 | new_pb = gdk_pixbuf_scale_simple (pb, width - options.picture_data.inc, 130 | height - options.picture_data.inc, GDK_INTERP_HYPER); 131 | if (new_pb) 132 | { 133 | gtk_image_set_from_pixbuf (GTK_IMAGE (picture), new_pb); 134 | g_object_unref (pb); 135 | } 136 | break; 137 | } 138 | } 139 | 140 | static void 141 | rotate_cb (GtkWidget *w, gint type) 142 | { 143 | GdkPixbuf *new_pb = NULL; 144 | GdkPixbuf *pb = gtk_image_get_pixbuf (GTK_IMAGE (picture)); 145 | 146 | if (!pb) 147 | { 148 | g_printerr ("picture: can't get pixbuf\n"); 149 | return; 150 | } 151 | 152 | switch (type) 153 | { 154 | case ROTATE_LEFT: 155 | new_pb = gdk_pixbuf_rotate_simple (pb, GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE); 156 | break; 157 | case ROTATE_RIGHT: 158 | new_pb = gdk_pixbuf_rotate_simple (pb, GDK_PIXBUF_ROTATE_CLOCKWISE); 159 | break; 160 | case ROTATE_FLIP_VERT: 161 | new_pb = gdk_pixbuf_flip (pb, FALSE); 162 | break; 163 | case ROTATE_FLIP_HOR: 164 | new_pb = gdk_pixbuf_flip (pb, TRUE); 165 | break; 166 | } 167 | 168 | if (new_pb) 169 | { 170 | gtk_image_set_from_pixbuf (GTK_IMAGE (picture), new_pb); 171 | g_object_unref (pb); 172 | } 173 | } 174 | 175 | static void 176 | create_popup_menu () 177 | { 178 | GtkWidget *mi; 179 | 180 | popup_menu = gtk_menu_new (); 181 | gtk_menu_set_reserve_toggle_size (GTK_MENU (popup_menu), FALSE); 182 | 183 | mi = gtk_menu_item_new_with_label (_("Fit to window")); 184 | gtk_widget_show (mi); 185 | gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi); 186 | g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (change_size_cb), GINT_TO_POINTER (SIZE_FIT)); 187 | 188 | mi = gtk_menu_item_new_with_label (_("Original size")); 189 | gtk_widget_show (mi); 190 | gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi); 191 | g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (change_size_cb), GINT_TO_POINTER (SIZE_ORIG)); 192 | 193 | mi = gtk_menu_item_new_with_label (_("Increase size")); 194 | gtk_widget_show (mi); 195 | gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi); 196 | g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (change_size_cb), GINT_TO_POINTER (SIZE_INC)); 197 | 198 | mi = gtk_menu_item_new_with_label (_("Decrease size")); 199 | gtk_widget_show (mi); 200 | gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi); 201 | g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (change_size_cb), GINT_TO_POINTER (SIZE_DEC)); 202 | 203 | mi = gtk_separator_menu_item_new (); 204 | gtk_widget_show (mi); 205 | gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi); 206 | 207 | mi = gtk_menu_item_new_with_label (_("Rotate left")); 208 | gtk_widget_show (mi); 209 | gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi); 210 | g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (rotate_cb), GINT_TO_POINTER (ROTATE_LEFT)); 211 | 212 | mi = gtk_menu_item_new_with_label (_("Rotate right")); 213 | gtk_widget_show (mi); 214 | gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi); 215 | g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (rotate_cb), GINT_TO_POINTER (ROTATE_RIGHT)); 216 | 217 | mi = gtk_menu_item_new_with_label (_("Flip vertical")); 218 | gtk_widget_show (mi); 219 | gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi); 220 | g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (rotate_cb), GINT_TO_POINTER (ROTATE_FLIP_VERT)); 221 | 222 | mi = gtk_menu_item_new_with_label (_("Flip horizontal")); 223 | gtk_widget_show (mi); 224 | gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), mi); 225 | g_signal_connect (G_OBJECT (mi), "activate", G_CALLBACK (rotate_cb), GINT_TO_POINTER (ROTATE_FLIP_HOR)); 226 | } 227 | 228 | static gboolean 229 | button_handler (GtkWidget *w, GdkEventButton *ev, gpointer data) 230 | { 231 | if (ev->button == 3) 232 | { 233 | #if GTK_CHECK_VERSION(3,22,0) 234 | gtk_menu_popup_at_pointer (GTK_MENU (popup_menu), NULL); 235 | #else 236 | gtk_menu_popup (GTK_MENU (popup_menu), NULL, NULL, NULL, NULL, ev->button, ev->time); 237 | #endif 238 | return TRUE; 239 | } 240 | 241 | return FALSE; 242 | } 243 | 244 | static gboolean 245 | key_handler (GtkWidget *w, GdkEventKey *ev, gpointer data) 246 | { 247 | return FALSE; 248 | } 249 | 250 | GtkWidget * 251 | picture_create_widget (GtkWidget * dlg) 252 | { 253 | GtkWidget *sw, *ev; 254 | 255 | sw = gtk_scrolled_window_new (NULL, NULL); 256 | gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_NONE); 257 | gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), options.hscroll_policy, options.vscroll_policy); 258 | 259 | viewport = gtk_viewport_new (gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (sw)), 260 | gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (sw))); 261 | gtk_container_add (GTK_CONTAINER (sw), viewport); 262 | 263 | ev = gtk_event_box_new (); 264 | gtk_container_add (GTK_CONTAINER (viewport), ev); 265 | 266 | picture = gtk_image_new (); 267 | gtk_container_add (GTK_CONTAINER (ev), picture); 268 | 269 | /* load picture */ 270 | if (options.common_data.uri && 271 | g_file_test (options.common_data.uri, G_FILE_TEST_EXISTS)) 272 | load_picture (options.common_data.uri); 273 | else 274 | gtk_image_set_from_icon_name (GTK_IMAGE (picture), "image-missing", GTK_ICON_SIZE_DIALOG); 275 | 276 | if (loaded && !animated) 277 | { 278 | create_popup_menu (); 279 | g_signal_connect (G_OBJECT (ev), "button-press-event", G_CALLBACK (button_handler), NULL); 280 | g_signal_connect (G_OBJECT (ev), "key-press-event", G_CALLBACK (key_handler), NULL); 281 | } 282 | 283 | return sw; 284 | } 285 | -------------------------------------------------------------------------------- /src/print.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of YAD. 3 | * 4 | * YAD 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 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * YAD is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with YAD. If not, see . 16 | * 17 | * Copyright (C) 2008-2019, Victor Ananjevsky 18 | */ 19 | 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | 26 | #include "yad.h" 27 | 28 | #define HEADER_HEIGHT (10*72/25.4) 29 | #define HEADER_GAP (3*72/25.4) 30 | #define HEADER_FONT "Sans 11" 31 | 32 | #define FONTNAME "Monospace" 33 | #define FONTSIZE 11.0 34 | 35 | static gchar **text; 36 | static gint nlines, npages; 37 | 38 | static PangoFontDescription *fdesc = NULL; 39 | 40 | static void 41 | draw_header (GtkPrintContext * cnt, gint pn, gint pc) 42 | { 43 | cairo_t *cr; 44 | PangoFontDescription *desc; 45 | PangoLayout *layout; 46 | gint pw, tw, th; 47 | gchar *page; 48 | 49 | cr = gtk_print_context_get_cairo_context (cnt); 50 | pw = gtk_print_context_get_width (cnt); 51 | 52 | layout = gtk_print_context_create_pango_layout (cnt); 53 | 54 | desc = pango_font_description_from_string (HEADER_FONT); 55 | pango_layout_set_font_description (layout, desc); 56 | pango_font_description_free (desc); 57 | 58 | pango_layout_set_text (layout, options.common_data.uri, -1); 59 | pango_layout_get_pixel_size (layout, &tw, &th); 60 | if (tw > pw) 61 | { 62 | pango_layout_set_width (layout, pw); 63 | pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_START); 64 | pango_layout_get_pixel_size (layout, &tw, &th); 65 | } 66 | 67 | cairo_move_to (cr, (pw - tw) / 2, (HEADER_HEIGHT - th) / 2); 68 | pango_cairo_show_layout (cr, layout); 69 | 70 | page = g_strdup_printf ("%d/%d", pn, pc); 71 | pango_layout_set_text (layout, page, -1); 72 | g_free (page); 73 | 74 | pango_layout_set_width (layout, -1); 75 | pango_layout_get_pixel_size (layout, &tw, &th); 76 | cairo_move_to (cr, pw - tw - 4, (HEADER_HEIGHT - th) / 2); 77 | pango_cairo_show_layout (cr, layout); 78 | 79 | g_object_unref (layout); 80 | 81 | cairo_move_to (cr, 0.0, HEADER_HEIGHT); 82 | cairo_line_to (cr, pw, HEADER_HEIGHT); 83 | 84 | cairo_set_source_rgb (cr, 0, 0, 0); 85 | cairo_set_line_width (cr, 1); 86 | cairo_stroke (cr); 87 | } 88 | 89 | static void 90 | begin_print_text (GtkPrintOperation * op, GtkPrintContext * cnt, gpointer data) 91 | { 92 | gchar *buf; 93 | gint i = 0; 94 | gdouble ph; 95 | 96 | /* load file */ 97 | g_file_get_contents (options.common_data.uri, &buf, NULL, NULL); 98 | text = g_strsplit (buf, "\n", 0); 99 | g_free (buf); 100 | 101 | while (text[i] != NULL) 102 | i++; 103 | 104 | ph = gtk_print_context_get_height (cnt); 105 | if (options.print_data.headers) 106 | ph -= HEADER_HEIGHT + HEADER_GAP; 107 | 108 | nlines = ph / FONTSIZE; 109 | npages = i / nlines + 1; 110 | gtk_print_operation_set_n_pages (op, npages); 111 | 112 | /* set font */ 113 | if (options.common_data.font) 114 | fdesc = pango_font_description_from_string (options.common_data.font); 115 | else 116 | { 117 | fdesc = pango_font_description_from_string (FONTNAME); 118 | pango_font_description_set_size (fdesc, FONTSIZE * PANGO_SCALE); 119 | } 120 | } 121 | 122 | static void 123 | draw_page_text (GtkPrintOperation * op, GtkPrintContext * cnt, gint page, gpointer data) 124 | { 125 | cairo_t *cr; 126 | PangoLayout *layout; 127 | gint i, line; 128 | 129 | cr = gtk_print_context_get_cairo_context (cnt); 130 | 131 | /* create header */ 132 | if (options.print_data.headers) 133 | draw_header (cnt, page + 1, npages); 134 | 135 | /* add text */ 136 | layout = gtk_print_context_create_pango_layout (cnt); 137 | pango_layout_set_font_description (layout, fdesc); 138 | 139 | cairo_move_to (cr, 0, HEADER_HEIGHT + HEADER_GAP); 140 | 141 | line = page * nlines; 142 | for (i = 0; i < nlines; i++) 143 | { 144 | if (text[line + i] == NULL) 145 | break; 146 | pango_layout_set_text (layout, text[line + i], -1); 147 | pango_cairo_show_layout (cr, layout); 148 | cairo_rel_move_to (cr, 0, FONTSIZE); 149 | } 150 | 151 | g_object_unref (layout); 152 | } 153 | 154 | static void 155 | draw_page_image (GtkPrintOperation * op, GtkPrintContext * cnt, gint page, gpointer data) 156 | { 157 | cairo_t *cr; 158 | GdkPixbuf *pb, *spb; 159 | guint iw, ih; 160 | gdouble pw, ph; 161 | gdouble factor; 162 | 163 | cr = gtk_print_context_get_cairo_context (cnt); 164 | 165 | pw = gtk_print_context_get_width (cnt); 166 | ph = gtk_print_context_get_height (cnt); 167 | 168 | /* create header */ 169 | if (options.print_data.headers) 170 | { 171 | ph -= HEADER_HEIGHT + HEADER_GAP; 172 | draw_header (cnt, 1, 1); 173 | } 174 | 175 | /* scale image to page size */ 176 | pb = gdk_pixbuf_new_from_file (options.common_data.uri, NULL); 177 | iw = gdk_pixbuf_get_width (pb); 178 | ih = gdk_pixbuf_get_height (pb); 179 | 180 | if (pw < iw || ph < ih) 181 | { 182 | factor = MIN (pw / iw, ph / ih); 183 | factor = (factor > 1.0) ? 1.0 : factor; 184 | spb = gdk_pixbuf_scale_simple (pb, iw * factor, ih * factor, GDK_INTERP_HYPER); 185 | } 186 | else 187 | spb = g_object_ref (pb); 188 | g_object_unref (pb); 189 | 190 | /* add image to surface */ 191 | gdk_cairo_set_source_pixbuf (cr, spb, 0.0, HEADER_HEIGHT + HEADER_GAP); 192 | cairo_paint (cr); 193 | g_object_unref (spb); 194 | } 195 | 196 | static void 197 | raw_print_done (GtkPrintJob * job, gint * ret, GError * err) 198 | { 199 | if (err) 200 | { 201 | g_printerr (_("Printing failed: %s\n"), err->message); 202 | *ret = 1; 203 | } 204 | yad_exit (options.data.def_resp); 205 | } 206 | 207 | static void 208 | size_allocate_cb (GtkWidget * w, GtkAllocation * al, gpointer data) 209 | { 210 | gtk_widget_set_size_request (w, al->width, -1); 211 | } 212 | 213 | static gboolean 214 | save_settings (GtkPrintSettings *print_settings, GtkPageSetup *page_setup) 215 | { 216 | GKeyFile *kf; 217 | gchar *fn, *contents; 218 | gboolean res = 0; 219 | 220 | kf = g_key_file_new (); 221 | 222 | if (print_settings) 223 | gtk_print_settings_to_key_file (print_settings, kf, NULL); 224 | 225 | if (page_setup) 226 | gtk_page_setup_to_key_file (page_setup, kf, NULL); 227 | 228 | contents = g_key_file_to_data (kf, NULL, NULL); 229 | g_key_file_free (kf); 230 | 231 | fn = g_build_filename (g_get_user_config_dir (), "yad", NULL); 232 | g_mkdir_with_parents (fn, 0700); 233 | g_free (fn); 234 | 235 | fn = g_build_filename (g_get_user_config_dir (), "yad", "print.conf", NULL); 236 | res = g_file_set_contents (fn, contents, -1, NULL); 237 | g_free (fn); 238 | g_free (contents); 239 | 240 | if (!res) 241 | g_printerr (_("Cannot save print settings file: %s\n"), strerror (errno)); 242 | 243 | return res; 244 | } 245 | 246 | gint 247 | yad_print_run (void) 248 | { 249 | GtkWidget *dlg; 250 | GtkWidget *box, *img, *lbl; 251 | gchar *uri, *fn, *job_name = NULL; 252 | GtkPrintCapabilities pcap; 253 | GtkPrintOperationAction act = GTK_PRINT_OPERATION_ACTION_PRINT; 254 | GtkPrintSettings *print_settings = NULL; 255 | GtkPageSetup *page_setup = NULL; 256 | gint resp, ret = 0; 257 | GError *err = NULL; 258 | 259 | /* check if file is exists */ 260 | if (options.common_data.uri && options.common_data.uri[0]) 261 | { 262 | if (!g_file_test (options.common_data.uri, G_FILE_TEST_EXISTS)) 263 | { 264 | g_printerr (_("File %s not found.\n"), options.common_data.uri); 265 | return 1; 266 | } 267 | } 268 | else 269 | { 270 | g_printerr (_("Filename is not specified.\n")); 271 | return 1; 272 | } 273 | 274 | /* load previously saved print settings */ 275 | fn = g_build_filename (g_get_user_config_dir (), "yad", "print.conf", NULL); 276 | if (g_file_test (fn, G_FILE_TEST_EXISTS)) 277 | { 278 | print_settings = gtk_print_settings_new_from_file (fn, NULL); 279 | page_setup = gtk_page_setup_new_from_file (fn, NULL); 280 | } 281 | g_free (fn); 282 | 283 | if (!print_settings) 284 | print_settings = gtk_print_settings_new (); 285 | if (!page_setup) 286 | page_setup = gtk_page_setup_new (); 287 | 288 | /* create print dialog */ 289 | dlg = gtk_print_unix_dialog_new (options.data.dialog_title, NULL); 290 | gtk_window_set_type_hint (GTK_WINDOW (dlg), GDK_WINDOW_TYPE_HINT_NORMAL); 291 | gtk_print_unix_dialog_set_embed_page_setup (GTK_PRINT_UNIX_DIALOG (dlg), TRUE); 292 | pcap = GTK_PRINT_CAPABILITY_PAGE_SET | GTK_PRINT_CAPABILITY_COPIES | 293 | GTK_PRINT_CAPABILITY_COLLATE | GTK_PRINT_CAPABILITY_REVERSE | 294 | GTK_PRINT_CAPABILITY_NUMBER_UP | GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT; 295 | if (options.common_data.preview && options.print_data.type != YAD_PRINT_RAW) 296 | pcap |= GTK_PRINT_CAPABILITY_PREVIEW; 297 | gtk_print_unix_dialog_set_manual_capabilities (GTK_PRINT_UNIX_DIALOG (dlg), pcap); 298 | 299 | uri = (gchar *) gtk_print_settings_get(print_settings, "output-uri"); 300 | if (uri == NULL) 301 | { 302 | uri = g_build_filename (g_get_current_dir (), "yad.pdf", NULL); 303 | gtk_print_settings_set (print_settings, "output-uri", g_filename_to_uri (uri, NULL, NULL)); 304 | g_free (uri); 305 | } 306 | 307 | gtk_print_unix_dialog_set_settings (GTK_PRINT_UNIX_DIALOG (dlg), print_settings); 308 | gtk_print_unix_dialog_set_page_setup (GTK_PRINT_UNIX_DIALOG (dlg), page_setup); 309 | 310 | /* set window behavior */ 311 | gtk_widget_set_name (dlg, "yad-dialog-window"); 312 | if (options.data.sticky) 313 | gtk_window_stick (GTK_WINDOW (dlg)); 314 | gtk_window_set_resizable (GTK_WINDOW (dlg), !options.data.fixed); 315 | gtk_window_set_keep_above (GTK_WINDOW (dlg), options.data.ontop); 316 | gtk_window_set_decorated (GTK_WINDOW (dlg), !options.data.undecorated); 317 | gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dlg), options.data.skip_taskbar); 318 | gtk_window_set_skip_pager_hint (GTK_WINDOW (dlg), options.data.skip_taskbar); 319 | 320 | /* set window size and position */ 321 | gtk_window_set_default_size (GTK_WINDOW (dlg), options.data.width, options.data.height); 322 | if (options.data.center) 323 | gtk_window_set_position (GTK_WINDOW (dlg), GTK_WIN_POS_CENTER); 324 | else if (options.data.mouse) 325 | gtk_window_set_position (GTK_WINDOW (dlg), GTK_WIN_POS_MOUSE); 326 | 327 | /* create yad's top box */ 328 | if (options.data.dialog_text || options.data.dialog_image) 329 | { 330 | #if !GTK_CHECK_VERSION(3,0,0) 331 | box = gtk_hbox_new (FALSE, 0); 332 | #else 333 | box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); 334 | #endif 335 | 336 | if (options.data.dialog_image) 337 | { 338 | GdkPixbuf *pb = NULL; 339 | 340 | pb = get_pixbuf (options.data.dialog_image, YAD_BIG_ICON, FALSE); 341 | img = gtk_image_new_from_pixbuf (pb); 342 | if (pb) 343 | g_object_unref (pb); 344 | 345 | gtk_widget_set_name (img, "yad-dialog-image"); 346 | gtk_box_pack_start (GTK_BOX (box), img, FALSE, FALSE, 2); 347 | } 348 | if (options.data.dialog_text) 349 | { 350 | gchar *buf = g_strcompress (options.data.dialog_text); 351 | 352 | lbl = gtk_label_new (NULL); 353 | if (!options.data.no_markup) 354 | gtk_label_set_markup (GTK_LABEL (lbl), buf); 355 | else 356 | gtk_label_set_text (GTK_LABEL (lbl), buf); 357 | gtk_widget_set_name (lbl, "yad-dialog-label"); 358 | gtk_label_set_selectable (GTK_LABEL (lbl), options.data.selectable_labels); 359 | #if !GTK_CHECK_VERSION(3,0,0) 360 | gtk_misc_set_alignment (GTK_MISC (lbl), options.data.text_align, 0.5); 361 | #else 362 | gtk_label_set_xalign (GTK_LABEL (lbl), options.data.text_align); 363 | #endif 364 | if (options.data.geometry || options.data.width != -1) 365 | gtk_label_set_line_wrap (GTK_LABEL (lbl), TRUE); 366 | gtk_box_pack_start (GTK_BOX (box), lbl, TRUE, TRUE, 2); 367 | g_signal_connect (G_OBJECT (lbl), "size-allocate", G_CALLBACK (size_allocate_cb), NULL); 368 | g_free (buf); 369 | } 370 | 371 | /* add tob box to dialog */ 372 | gtk_widget_show_all (box); 373 | gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))), box, TRUE, TRUE, 5); 374 | gtk_box_reorder_child (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))), box, 0); 375 | } 376 | 377 | do 378 | { 379 | resp = gtk_dialog_run (GTK_DIALOG (dlg)); 380 | switch (resp) 381 | { 382 | case GTK_RESPONSE_APPLY: /* ask for preview */ 383 | act = GTK_PRINT_OPERATION_ACTION_PREVIEW; 384 | case GTK_RESPONSE_OK: /* run print */ 385 | print_settings = gtk_print_unix_dialog_get_settings (GTK_PRINT_UNIX_DIALOG (dlg)); 386 | page_setup = gtk_print_unix_dialog_get_page_setup (GTK_PRINT_UNIX_DIALOG (dlg)); 387 | job_name = g_strdup_printf ("yad-%s-%d", g_path_get_basename (options.common_data.uri), getpid ()); 388 | if (options.print_data.type != YAD_PRINT_RAW) 389 | { 390 | /* print text or image */ 391 | GtkPrintOperation *op = gtk_print_operation_new (); 392 | gtk_print_operation_set_unit (op, GTK_UNIT_POINTS); 393 | gtk_print_operation_set_print_settings (op, print_settings); 394 | gtk_print_operation_set_default_page_setup (op, page_setup); 395 | gtk_print_operation_set_job_name (op, job_name); 396 | 397 | switch (options.print_data.type) 398 | { 399 | case YAD_PRINT_TEXT: 400 | g_signal_connect (G_OBJECT (op), "begin-print", G_CALLBACK (begin_print_text), NULL); 401 | g_signal_connect (G_OBJECT (op), "draw-page", G_CALLBACK (draw_page_text), NULL); 402 | break; 403 | case YAD_PRINT_IMAGE: 404 | gtk_print_operation_set_n_pages (op, 1); 405 | g_signal_connect (G_OBJECT (op), "draw-page", G_CALLBACK (draw_page_image), NULL); 406 | break; 407 | default:; 408 | } 409 | 410 | if (gtk_print_operation_run (op, act, NULL, &err) == GTK_PRINT_OPERATION_RESULT_ERROR) 411 | { 412 | g_printerr (_("Printing failed: %s\n"), err->message); 413 | ret = 1; 414 | } 415 | 416 | /* for a CUPS printer op could display another print settings/page setup dialog */ 417 | print_settings = gtk_print_operation_get_print_settings (op); 418 | page_setup = gtk_print_operation_get_default_page_setup (op); 419 | } 420 | else 421 | { 422 | /* print raw ps or pdf data */ 423 | GtkPrinter *prnt; 424 | GtkPrintJob *job; 425 | 426 | prnt = gtk_print_unix_dialog_get_selected_printer (GTK_PRINT_UNIX_DIALOG (dlg)); 427 | 428 | if (g_str_has_suffix (options.common_data.uri, ".ps")) 429 | { 430 | if (!gtk_printer_accepts_ps (prnt)) 431 | { 432 | g_printerr (_("Printer doesn't support ps format.\n")); 433 | ret = 1; 434 | } 435 | } 436 | else if (g_str_has_suffix (options.common_data.uri, ".pdf")) 437 | { 438 | if (!gtk_printer_accepts_pdf (prnt)) 439 | { 440 | g_printerr (_("Printer doesn't support pdf format.\n")); 441 | ret = 1; 442 | } 443 | } 444 | else 445 | { 446 | g_printerr (_("This file type is not supported for raw printing.\n")); 447 | ret = 1; 448 | } 449 | if (ret == 1) 450 | break; 451 | 452 | job = gtk_print_job_new (job_name, prnt, print_settings, page_setup); 453 | if (gtk_print_job_set_source_file (job, options.common_data.uri, &err)) 454 | { 455 | gtk_print_job_send (job, (GtkPrintJobCompleteFunc) raw_print_done, &ret, NULL); 456 | gtk_main (); 457 | } 458 | else 459 | { 460 | g_printerr (_("Load source file failed: %s\n"), err->message); 461 | ret = 1; 462 | } 463 | } 464 | break; 465 | default: 466 | ret = 1; 467 | break; 468 | } 469 | } 470 | while (resp == GTK_RESPONSE_APPLY); 471 | 472 | gtk_widget_destroy (dlg); 473 | 474 | if (0 == ret) 475 | ret = ! save_settings(print_settings, page_setup); 476 | 477 | return ret; 478 | } 479 | -------------------------------------------------------------------------------- /src/progress.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of YAD. 3 | * 4 | * YAD 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 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * YAD is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with YAD. If not, see . 16 | * 17 | * Copyright (C) 2008-2019, Victor Ananjevsky 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "yad.h" 28 | 29 | static GSList *progress_bars = NULL; 30 | static guint nbars = 0; 31 | 32 | static GtkWidget *progress_log; 33 | static GtkTextBuffer *log_buffer; 34 | 35 | static gboolean single_mode = FALSE; 36 | 37 | static gboolean 38 | pulsate_progress_bar (GtkProgressBar *bar) 39 | { 40 | gtk_progress_bar_pulse (bar); 41 | return TRUE; 42 | } 43 | 44 | static gboolean 45 | handle_stdin (GIOChannel *channel, GIOCondition condition, gpointer data) 46 | { 47 | static guint single_mode_pulsate_timeout = 0; 48 | float percentage = 0.0; 49 | 50 | if ((condition == G_IO_IN) || (condition == G_IO_IN + G_IO_HUP)) 51 | { 52 | GString *string; 53 | gchar **value; 54 | GError *err = NULL; 55 | 56 | string = g_string_new (NULL); 57 | 58 | while (channel->is_readable != TRUE) 59 | usleep (100); 60 | 61 | do 62 | { 63 | gint status, num; 64 | GtkProgressBar *pb; 65 | YadProgressBar *b; 66 | 67 | do 68 | { 69 | status = g_io_channel_read_line_string (channel, string, NULL, &err); 70 | 71 | while (gtk_events_pending ()) 72 | gtk_main_iteration (); 73 | } 74 | while (status == G_IO_STATUS_AGAIN); 75 | 76 | if (status != G_IO_STATUS_NORMAL) 77 | { 78 | if (err) 79 | { 80 | g_printerr ("yad_multi_progress_handle_stdin(): %s\n", err->message); 81 | g_error_free (err); 82 | err = NULL; 83 | } 84 | /* stop handling */ 85 | g_io_channel_shutdown (channel, TRUE, NULL); 86 | return FALSE; 87 | } 88 | 89 | if (single_mode) 90 | { 91 | value = g_new0 (gchar *, 2); 92 | value[1] = g_strdup (string->str); 93 | num = 0; 94 | } 95 | else 96 | { 97 | value = g_strsplit (string->str, ":", 2); 98 | num = atoi (value[0]) - 1; 99 | if (num < 0 || num > nbars - 1) 100 | continue; 101 | } 102 | 103 | pb = GTK_PROGRESS_BAR (g_slist_nth_data (progress_bars, num)); 104 | b = (YadProgressBar *) g_slist_nth_data (options.progress_data.bars, num); 105 | 106 | if (value[1] && value[1][0] == '#') 107 | { 108 | gchar *match; 109 | 110 | /* We have a comment, so let's try to change the label */ 111 | match = g_strcompress (value[1] + 1); 112 | strip_new_line (match); 113 | if (options.progress_data.log) 114 | { 115 | gchar *logline; 116 | GtkTextIter end; 117 | 118 | logline = g_strdup_printf ("%s\n", match); /* add new line */ 119 | gtk_text_buffer_get_end_iter (log_buffer, &end); 120 | gtk_text_buffer_insert (log_buffer, &end, logline, -1); 121 | g_free (logline); 122 | 123 | /* scroll to end */ 124 | while (gtk_events_pending ()) 125 | gtk_main_iteration (); 126 | gtk_text_buffer_get_end_iter (log_buffer, &end); 127 | gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (progress_log), &end, 0, FALSE, 0, 0); 128 | } 129 | else 130 | { 131 | if (!options.common_data.hide_text) 132 | gtk_progress_bar_set_text (pb, match); 133 | } 134 | g_free (match); 135 | } 136 | else 137 | { 138 | if (options.progress_data.pulsate && value[1] && b->type == YAD_PROGRESS_PULSE) 139 | { 140 | if (single_mode_pulsate_timeout == 0) 141 | single_mode_pulsate_timeout = g_timeout_add (100, (GSourceFunc) pulsate_progress_bar, pb); 142 | gtk_progress_bar_pulse (pb); 143 | } 144 | else if (value[1] && b->type == YAD_PROGRESS_PULSE) 145 | gtk_progress_bar_pulse (pb); 146 | else if (value[1] && b->type == YAD_PROGRESS_PERM) 147 | { 148 | guint id; 149 | 150 | if (strncmp (value[1], "start", 5) == 0) 151 | { 152 | id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (pb), "id")); 153 | if (id == 0) 154 | { 155 | id = g_timeout_add (100, (GSourceFunc) pulsate_progress_bar, pb); 156 | g_object_set_data (G_OBJECT (pb), "id", GINT_TO_POINTER (id)); 157 | } 158 | } 159 | else if (strncmp (value[1], "stop", 4) == 0) 160 | { 161 | id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (pb), "id")); 162 | if (id > 0) 163 | { 164 | g_source_remove (id); 165 | g_object_set_data (G_OBJECT (pb), "id", GINT_TO_POINTER (0)); 166 | } 167 | } 168 | } 169 | 170 | /* step: in version 0.42.x single-progress pulsate can set its percentange, 171 | which is desirable to be able to --auto-close the dialog at 100%. There is no 172 | harm to also let multi-progress PERM and PULSE bars set their percentage. */ 173 | /*{*/ 174 | if (!value[1] || !g_ascii_isdigit (*value[1])) 175 | continue; 176 | 177 | /* Now try to convert the thing to a number */ 178 | percentage = atoi (value[1]); 179 | if (percentage >= 100) 180 | gtk_progress_bar_set_fraction (pb, 1.0); 181 | else 182 | gtk_progress_bar_set_fraction (pb, percentage / 100.0); 183 | 184 | /* Check if all of progress bars reaches 100% */ 185 | if (options.progress_data.autoclose && options.plug == -1) 186 | { 187 | guint i; 188 | gboolean close = TRUE; 189 | gboolean need_close = FALSE; 190 | 191 | if (options.progress_data.watch_bar > 0 && options.progress_data.watch_bar <= nbars) 192 | { 193 | GtkProgressBar *cpb = GTK_PROGRESS_BAR (g_slist_nth_data (progress_bars, 194 | options.progress_data.watch_bar - 1)); 195 | 196 | need_close = TRUE; 197 | if (gtk_progress_bar_get_fraction (cpb) != 1.0) 198 | close = FALSE; 199 | } 200 | else 201 | { 202 | for (i = 0; i < nbars; i++) 203 | { 204 | GtkProgressBar *cpb = GTK_PROGRESS_BAR (g_slist_nth_data (progress_bars, i)); 205 | YadProgressBar *cb = (YadProgressBar *) g_slist_nth_data (options.progress_data.bars, i); 206 | 207 | if (cb->type != YAD_PROGRESS_PULSE) 208 | { 209 | need_close = TRUE; 210 | if (gtk_progress_bar_get_fraction (cpb) != 1.0) 211 | { 212 | close = FALSE; 213 | break; 214 | } 215 | } 216 | } 217 | } 218 | 219 | if (need_close && close) 220 | yad_exit (options.data.def_resp); 221 | } 222 | /*}*/ 223 | } 224 | } 225 | while (g_io_channel_get_buffer_condition (channel) == G_IO_IN); 226 | g_string_free (string, TRUE); 227 | } 228 | 229 | if ((condition != G_IO_IN) && (condition != G_IO_IN + G_IO_HUP)) 230 | { 231 | g_io_channel_shutdown (channel, TRUE, NULL); 232 | 233 | if (options.progress_data.autoclose && options.plug == -1) 234 | yad_exit (options.data.def_resp); 235 | 236 | return FALSE; 237 | } 238 | return TRUE; 239 | } 240 | 241 | GtkWidget * 242 | progress_create_widget (GtkWidget *dlg) 243 | { 244 | GtkWidget *table; 245 | GIOChannel *channel; 246 | GSList *b; 247 | gint i = 0; 248 | 249 | nbars = g_slist_length (options.progress_data.bars); 250 | if (nbars < 1) 251 | { 252 | YadProgressBar *bar = g_new0 (YadProgressBar, 1); 253 | 254 | if (options.debug) 255 | g_printerr (_("WARNING: the old-style progress dialog option is deprecated: use --bar style instead\n")); 256 | 257 | if (options.progress_data.pulsate) 258 | bar->type = YAD_PROGRESS_PULSE; 259 | else if (options.progress_data.rtl) 260 | bar->type = YAD_PROGRESS_RTL; 261 | else 262 | bar->type = YAD_PROGRESS_NORMAL; 263 | 264 | #if GTK_CHECK_VERSION(3,0,0) 265 | /* #else handled in "maintain-gtk2" further down */ 266 | /* writes a fixed label on the side of the bar */ 267 | if (options.progress_data.progress_text) 268 | bar->name = options.progress_data.progress_text; 269 | #endif 270 | 271 | options.progress_data.bars = g_slist_append (options.progress_data.bars, bar); 272 | nbars = 1; 273 | 274 | options.progress_data.watch_bar = 1; 275 | 276 | single_mode = TRUE; 277 | } 278 | 279 | #if !GTK_CHECK_VERSION(3,0,0) 280 | if (options.common_data.vertical) 281 | table = gtk_table_new (2, nbars, FALSE); 282 | else 283 | table = gtk_table_new (nbars, 2, FALSE); 284 | #else 285 | table = gtk_grid_new (); 286 | gtk_grid_set_row_spacing (GTK_GRID (table), 2); 287 | gtk_grid_set_column_spacing (GTK_GRID (table), 2); 288 | #endif 289 | 290 | for (b = options.progress_data.bars; b; b = b->next) 291 | { 292 | GtkWidget *l, *w; 293 | YadProgressBar *p = (YadProgressBar *) b->data; 294 | 295 | /* add label */ 296 | l = gtk_label_new (NULL); 297 | if (options.data.no_markup) 298 | gtk_label_set_text (GTK_LABEL (l), p->name); 299 | else 300 | gtk_label_set_markup (GTK_LABEL (l), p->name); 301 | #if !GTK_CHECK_VERSION(3,0,0) 302 | gtk_misc_set_alignment (GTK_MISC (l), options.common_data.align, 0.5); 303 | #else 304 | gtk_label_set_xalign (GTK_LABEL (l), options.common_data.align); 305 | #endif 306 | if (options.common_data.vertical) 307 | #if !GTK_CHECK_VERSION(3,0,0) 308 | gtk_table_attach (GTK_TABLE (table), l, i, i + 1, 1, 2, GTK_FILL, 0, 2, 2); 309 | #else 310 | gtk_grid_attach (GTK_GRID (table), l, i, 1, 1, 1); 311 | #endif 312 | else 313 | #if !GTK_CHECK_VERSION(3,0,0) 314 | gtk_table_attach (GTK_TABLE (table), l, 0, 1, i, i + 1, GTK_FILL, 0, 2, 2); 315 | #else 316 | gtk_grid_attach (GTK_GRID (table), l, 0, i, 1, 1); 317 | #endif 318 | 319 | /* add progress bar */ 320 | w = gtk_progress_bar_new (); 321 | gtk_widget_set_name (w, "yad-progress-widget"); 322 | #if GTK_CHECK_VERSION(3,0,0) 323 | gtk_progress_bar_set_show_text (GTK_PROGRESS_BAR (w), !options.common_data.hide_text); 324 | #endif 325 | 326 | #if !GTK_CHECK_VERSION(3,0,0) 327 | /* The maintain-gtk2 branch keeps forward compatibility with master for GTK 3 builds only */ 328 | /* Here maintain-gtk2 keeps backward compatibility */ 329 | if (single_mode) 330 | { 331 | if (options.progress_data.percentage > 100) 332 | options.progress_data.percentage = 100; 333 | gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (w), options.progress_data.percentage / 100.0); 334 | 335 | /* writes updatable text inside the bar */ 336 | if (options.progress_data.progress_text && !options.common_data.hide_text) 337 | gtk_progress_bar_set_text (GTK_PROGRESS_BAR (w), options.progress_data.progress_text); 338 | } 339 | #endif 340 | 341 | if (p->type != YAD_PROGRESS_PULSE) 342 | { 343 | if (options.extra_data && options.extra_data[i]) 344 | { 345 | if (g_ascii_isdigit (*options.extra_data[i])) 346 | gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (w), atoi (options.extra_data[i]) / 100.0); 347 | } 348 | } 349 | else 350 | { 351 | if (options.extra_data && options.extra_data[i]) 352 | { 353 | if (g_ascii_isdigit (*options.extra_data[i])) 354 | gtk_progress_bar_set_pulse_step (GTK_PROGRESS_BAR (w), atoi (options.extra_data[i]) / 100.0); 355 | } 356 | } 357 | 358 | #if GTK_CHECK_VERSION(3,0,0) 359 | gtk_progress_bar_set_inverted (GTK_PROGRESS_BAR (w), p->type == YAD_PROGRESS_RTL); 360 | if (options.common_data.vertical) 361 | gtk_orientable_set_orientation (GTK_ORIENTABLE (w), GTK_ORIENTATION_VERTICAL); 362 | #else 363 | if (p->type == YAD_PROGRESS_RTL) 364 | { 365 | if (options.common_data.vertical) 366 | gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (w), GTK_PROGRESS_TOP_TO_BOTTOM); 367 | else 368 | gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (w), GTK_PROGRESS_RIGHT_TO_LEFT); 369 | } 370 | else 371 | { 372 | if (options.common_data.vertical) 373 | gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (w), GTK_PROGRESS_BOTTOM_TO_TOP); 374 | } 375 | #endif 376 | if (options.common_data.vertical) 377 | { 378 | #if !GTK_CHECK_VERSION(3,0,0) 379 | gtk_table_attach (GTK_TABLE (table), w, i, i + 1, 0, 1, 0, GTK_FILL | GTK_EXPAND, 2, 2); 380 | #else 381 | gtk_grid_attach (GTK_GRID (table), w, i, 0, 1, 1); 382 | gtk_widget_set_vexpand (w, TRUE); 383 | #endif 384 | } 385 | else 386 | { 387 | #if !GTK_CHECK_VERSION(3,0,0) 388 | gtk_table_attach (GTK_TABLE (table), w, 1, 2, i, i + 1, GTK_FILL | GTK_EXPAND, 0, 2, 2); 389 | #else 390 | gtk_grid_attach (GTK_GRID (table), w, 1, i, 1, 1); 391 | gtk_widget_set_hexpand (w, TRUE); 392 | #endif 393 | } 394 | 395 | progress_bars = g_slist_append (progress_bars, w); 396 | 397 | i++; 398 | } 399 | 400 | if (options.progress_data.log) 401 | { 402 | GtkWidget *ex, *sw; 403 | 404 | ex = gtk_expander_new (options.progress_data.log); 405 | gtk_expander_set_spacing (GTK_EXPANDER (ex), 2); 406 | gtk_expander_set_expanded (GTK_EXPANDER (ex), options.progress_data.log_expanded); 407 | 408 | #if !GTK_CHECK_VERSION(3,0,0) 409 | if (options.common_data.vertical) 410 | gtk_table_attach (GTK_TABLE (table), ex, 0, i + 1, 1, 2, GTK_FILL, 0, 2, 2); 411 | else 412 | gtk_table_attach (GTK_TABLE (table), ex, 0, 2, i, i + 1, GTK_FILL, 0, 2, 2); 413 | #else 414 | if (options.common_data.vertical) 415 | gtk_grid_attach (GTK_GRID (table), ex, 0, 2, i, 1); 416 | else 417 | gtk_grid_attach (GTK_GRID (table), ex, 0, i, 2, 1); 418 | #endif 419 | 420 | sw = gtk_scrolled_window_new (NULL, NULL); 421 | gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN); 422 | gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), options.hscroll_policy, options.vscroll_policy); 423 | #if GTK_CHECK_VERSION(3,22,0) 424 | gtk_scrolled_window_set_propagate_natural_height (GTK_SCROLLED_WINDOW (sw), TRUE); 425 | #endif 426 | gtk_container_add (GTK_CONTAINER (ex), sw); 427 | 428 | progress_log = gtk_text_view_new (); 429 | gtk_widget_set_name (progress_log, "yad-text-widget"); 430 | gtk_widget_set_size_request (progress_log, -1, options.progress_data.log_height); 431 | gtk_container_add (GTK_CONTAINER (sw), progress_log); 432 | 433 | log_buffer = gtk_text_buffer_new (NULL); 434 | gtk_text_view_set_buffer (GTK_TEXT_VIEW (progress_log), log_buffer); 435 | gtk_text_view_set_left_margin (GTK_TEXT_VIEW (progress_log), 5); 436 | gtk_text_view_set_right_margin (GTK_TEXT_VIEW (progress_log), 5); 437 | gtk_text_view_set_editable (GTK_TEXT_VIEW (progress_log), FALSE); 438 | gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (progress_log), FALSE); 439 | } 440 | 441 | channel = g_io_channel_unix_new (0); 442 | g_io_channel_set_encoding (channel, NULL, NULL); 443 | g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL); 444 | g_io_add_watch (channel, G_IO_IN | G_IO_HUP, handle_stdin, dlg); 445 | 446 | return table; 447 | } 448 | -------------------------------------------------------------------------------- /src/scale.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of YAD. 3 | * 4 | * YAD 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 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * YAD is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with YAD. If not, see . 16 | * 17 | * Copyright (C) 2008-2019, Victor Ananjevsky 18 | */ 19 | 20 | #include "yad.h" 21 | #include 22 | 23 | enum { 24 | PLUS_BTN = 0, 25 | MINUS_BTN, 26 | }; 27 | 28 | static GtkAdjustment *adj; 29 | static GtkWidget *scale; 30 | static GtkWidget *plus_btn = NULL; 31 | static GtkWidget *minus_btn = NULL; 32 | 33 | static void 34 | value_changed_cb (GtkWidget * w, gpointer data) 35 | { 36 | if (options.scale_data.enforce_step) 37 | { 38 | /* Make sure the new value corresponds to a step in the range. */ 39 | gdouble value = gtk_adjustment_get_value ((GtkAdjustment *)adj); 40 | gdouble new_value = (gdouble) round(value/options.scale_data.step) * options.scale_data.step; 41 | gtk_adjustment_set_value ((GtkAdjustment *)adj, new_value); 42 | } 43 | 44 | if (options.scale_data.print_partial) 45 | g_print ("%.0f\n", gtk_range_get_value (GTK_RANGE (scale))); 46 | 47 | if (options.scale_data.buttons) 48 | { 49 | gdouble v = gtk_range_get_value (GTK_RANGE (scale)); 50 | 51 | if (v >= options.scale_data.max_value) 52 | gtk_widget_set_sensitive (plus_btn, FALSE); 53 | else 54 | gtk_widget_set_sensitive (plus_btn, TRUE); 55 | 56 | if (v <= options.scale_data.min_value) 57 | gtk_widget_set_sensitive (minus_btn, FALSE); 58 | else 59 | gtk_widget_set_sensitive (minus_btn, TRUE); 60 | } 61 | } 62 | 63 | static void 64 | vb_pressed (GtkWidget *b, gpointer data) 65 | { 66 | gdouble v, cv = gtk_range_get_value (GTK_RANGE (scale)); 67 | 68 | switch (GPOINTER_TO_INT (data)) 69 | { 70 | case PLUS_BTN: 71 | v = cv + options.scale_data.step; 72 | gtk_range_set_value (GTK_RANGE (scale), MIN (v, options.scale_data.max_value)); 73 | break; 74 | case MINUS_BTN: 75 | v = cv - options.scale_data.step; 76 | gtk_range_set_value (GTK_RANGE (scale), MAX (v, options.scale_data.min_value)); 77 | break; 78 | } 79 | } 80 | 81 | GtkWidget * 82 | scale_create_widget (GtkWidget * dlg) 83 | { 84 | GtkWidget *w; 85 | gint page; 86 | 87 | if (options.scale_data.min_value >= options.scale_data.max_value) 88 | { 89 | g_printerr (_("Maximum value must be greater than minimum value.\n")); 90 | return NULL; 91 | } 92 | 93 | /* check for initial value */ 94 | if (options.scale_data.have_value) 95 | { 96 | if (options.scale_data.value < options.scale_data.min_value) 97 | { 98 | g_printerr (_("Initial value less than minimal.\n")); 99 | options.scale_data.value = options.scale_data.min_value; 100 | } 101 | else if (options.scale_data.value > options.scale_data.max_value) 102 | { 103 | g_printerr (_("Initial value greater than maximum.\n")); 104 | options.scale_data.value = options.scale_data.max_value; 105 | } 106 | } 107 | else 108 | options.scale_data.value = options.scale_data.min_value; 109 | 110 | page = options.scale_data.page == -1 ? options.scale_data.step * 10 : options.scale_data.page; 111 | /* this type conversion needs only for gtk-2.0 */ 112 | adj = (GtkAdjustment *) gtk_adjustment_new ((double) options.scale_data.value, 113 | (double) options.scale_data.min_value, 114 | (double) options.scale_data.max_value, 115 | (double) options.scale_data.step, 116 | (double) page, 117 | 0.0); 118 | if (options.common_data.vertical) 119 | { 120 | #if GTK_CHECK_VERSION(3,0,0) 121 | scale = gtk_scale_new (GTK_ORIENTATION_VERTICAL, GTK_ADJUSTMENT (adj)); 122 | #else 123 | scale = gtk_vscale_new (GTK_ADJUSTMENT (adj)); 124 | #endif 125 | gtk_range_set_inverted (GTK_RANGE (scale), !options.scale_data.invert); 126 | } 127 | else 128 | { 129 | #if GTK_CHECK_VERSION(3,0,0) 130 | scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (adj)); 131 | #else 132 | scale = gtk_hscale_new (GTK_ADJUSTMENT (adj)); 133 | #endif 134 | gtk_range_set_inverted (GTK_RANGE (scale), options.scale_data.invert); 135 | } 136 | gtk_widget_set_name (scale, "yad-scale-widget"); 137 | gtk_scale_set_digits (GTK_SCALE (scale), 0); 138 | 139 | if (options.scale_data.hide_value) 140 | gtk_scale_set_draw_value (GTK_SCALE (scale), FALSE); 141 | 142 | /* add marks */ 143 | if (options.scale_data.marks) 144 | { 145 | GtkPositionType pos; 146 | GSList *m = options.scale_data.marks; 147 | 148 | pos = options.common_data.vertical ? GTK_POS_LEFT : GTK_POS_BOTTOM; 149 | for (; m; m = m->next) 150 | { 151 | YadScaleMark *mark = (YadScaleMark *) m->data; 152 | gtk_scale_add_mark (GTK_SCALE (scale), mark->value, pos, mark->name); 153 | } 154 | } 155 | 156 | /* create container */ 157 | if (options.common_data.vertical) 158 | { 159 | #if GTK_CHECK_VERSION(3,0,0) 160 | w = gtk_box_new (GTK_ORIENTATION_VERTICAL, 1); 161 | #else 162 | w = gtk_vbox_new (FALSE, 1); 163 | #endif 164 | } 165 | else 166 | { 167 | #if GTK_CHECK_VERSION(3,0,0) 168 | w = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 1); 169 | #else 170 | w = gtk_hbox_new (FALSE, 1); 171 | #endif 172 | } 173 | 174 | /* create buttons */ 175 | if (options.scale_data.buttons) 176 | { 177 | minus_btn = gtk_button_new_with_label ("-"); 178 | gtk_button_set_relief (GTK_BUTTON (minus_btn), GTK_RELIEF_NONE); 179 | g_signal_connect (G_OBJECT (minus_btn), "clicked", G_CALLBACK (vb_pressed), GINT_TO_POINTER (MINUS_BTN)); 180 | gtk_widget_set_sensitive (minus_btn, (options.scale_data.value > options.scale_data.min_value)); 181 | 182 | plus_btn = gtk_button_new_with_label ("+"); 183 | gtk_button_set_relief (GTK_BUTTON (plus_btn), GTK_RELIEF_NONE); 184 | g_signal_connect (G_OBJECT (plus_btn), "clicked", G_CALLBACK (vb_pressed), GINT_TO_POINTER (PLUS_BTN)); 185 | gtk_widget_set_sensitive (plus_btn, (options.scale_data.value < options.scale_data.max_value)); 186 | } 187 | 188 | /* create complex widget */ 189 | if (options.scale_data.buttons) 190 | gtk_box_pack_start (GTK_BOX (w), options.common_data.vertical ? plus_btn : minus_btn, FALSE, FALSE, 0); 191 | 192 | gtk_box_pack_start (GTK_BOX (w), scale, TRUE, TRUE, 2); 193 | 194 | if (options.scale_data.buttons) 195 | gtk_box_pack_start (GTK_BOX (w), options.common_data.vertical ? minus_btn : plus_btn, FALSE, FALSE, 0); 196 | 197 | g_signal_connect (G_OBJECT (scale), "value-changed", G_CALLBACK (value_changed_cb), NULL); 198 | gtk_widget_grab_focus (scale); 199 | 200 | return w; 201 | } 202 | 203 | void 204 | scale_print_result (void) 205 | { 206 | g_print ("%.0f\n", gtk_range_get_value (GTK_RANGE (scale))); 207 | } 208 | -------------------------------------------------------------------------------- /src/tools.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of YAD. 3 | * 4 | * YAD 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 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * YAD is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with YAD. If not, see . 16 | * 17 | * Copyright (C) 2019, Victor Ananjevsky 18 | */ 19 | 20 | #include 21 | #include 22 | #pragma GCC diagnostic push 23 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 24 | #include 25 | #pragma GCC diagnostic pop 26 | #include 27 | 28 | #ifdef HAVE_SPELL 29 | #include 30 | #endif 31 | 32 | #ifdef HAVE_SOURCEVIEW 33 | #pragma GCC diagnostic push 34 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 35 | #if GTK_CHECK_VERSION(3,0,0) 36 | #include 37 | #else 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #endif 45 | #pragma GCC diagnostic pop 46 | #endif /* HAVE_SOURCEVIEW */ 47 | 48 | #include "cpicker.h" 49 | 50 | typedef enum { 51 | PANGO_SPEC, 52 | XFT_SPEC 53 | } FontType; 54 | 55 | static gboolean set_font_type (const gchar *name, const gchar *val, gpointer d, GError **err); 56 | static gboolean set_size_type (const gchar *name, const gchar *val, gpointer d, GError **err); 57 | 58 | static FontType font_type = XFT_SPEC; 59 | 60 | static gboolean pfd_mode = FALSE; 61 | static gboolean icon_mode = FALSE; 62 | static gboolean color_mode = FALSE; 63 | static gboolean mime = FALSE; 64 | static gboolean ver = FALSE; 65 | #ifdef HAVE_SPELL 66 | static gboolean langs_mode = FALSE; 67 | #endif 68 | #ifdef HAVE_SOURCEVIEW 69 | static gboolean themes_mode = FALSE; 70 | #endif 71 | gboolean pick_color = FALSE; 72 | 73 | static guint icon_size = 24; 74 | static gchar *icon_theme_name = NULL; 75 | 76 | static gchar **args = NULL; 77 | 78 | static GOptionEntry ents[] = { 79 | { "version", 'v', 0, G_OPTION_ARG_NONE, &ver, N_("Print version"), NULL }, 80 | #ifdef HAVE_SPELL 81 | { "show-langs", 0, 0, G_OPTION_ARG_NONE, &langs_mode, N_("Show list of spell languages"), NULL }, 82 | #endif 83 | #ifdef HAVE_SOURCEVIEW 84 | { "show-themes", 0, 0, G_OPTION_ARG_NONE, &themes_mode, N_("Show list of GtkSourceView themes"), NULL }, 85 | #endif 86 | { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args, NULL, N_("STRING ...") }, 87 | { NULL } 88 | }; 89 | 90 | static GOptionEntry pfd_ents[] = { 91 | { "pfd", 'f', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &pfd_mode, N_("Pango fonts description tools"), NULL }, 92 | { "xft", 'x', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, set_font_type, N_("Print font name in xft format"), NULL }, 93 | { "pango", 'p', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, set_font_type, N_("Print font name in pango format"), NULL }, 94 | { NULL } 95 | }; 96 | 97 | static GOptionEntry icon_ents[] = { 98 | { "icon", 'i', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &icon_mode, N_("Icon tools"), NULL }, 99 | { "mime", 'm', 0, G_OPTION_ARG_NONE, &mime, N_("Get icon name for mime type"), NULL }, 100 | { "size", 's', 0, G_OPTION_ARG_INT, &icon_size, N_("Use specified icon size"), N_("SIZE") }, 101 | { "type", 't', 0, G_OPTION_ARG_CALLBACK, set_size_type, N_("Get icon size from GtkIconSize type"), N_("TYPE") }, 102 | { "theme", 0, 0, G_OPTION_ARG_STRING, &icon_theme_name, N_("Use icon theme"), N_("THEME") }, 103 | { NULL } 104 | }; 105 | 106 | static GOptionEntry color_ents[] = { 107 | { "color", 'c', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &color_mode, N_("Color manipulation tools"), NULL }, 108 | { "pick", 0, 0, G_OPTION_ARG_NONE, &pick_color, N_("Pick up screen color"), NULL }, 109 | { NULL } 110 | }; 111 | 112 | static gboolean 113 | set_font_type (const gchar *name, const gchar *val, gpointer d, GError **err) 114 | { 115 | gint i = 1; 116 | 117 | if (name[i] == '-') 118 | i = 2; 119 | 120 | if (name[i] == 'p') 121 | font_type = PANGO_SPEC; 122 | else if (name[i] == 'x') 123 | font_type = XFT_SPEC; 124 | else 125 | return FALSE; 126 | 127 | return TRUE; 128 | } 129 | 130 | static gboolean 131 | set_size_type (const gchar *name, const gchar *val, gpointer d, GError **err) 132 | { 133 | gint w = 0, h = 0; 134 | 135 | if (strcasecmp (val, "MENU") == 0) 136 | gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &w, &h); 137 | else if (strcasecmp (val, "BUTTON") == 0) 138 | gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &w, &h); 139 | else if (strcasecmp (val, "SMALL_TOOLBAR") == 0) 140 | gtk_icon_size_lookup (GTK_ICON_SIZE_SMALL_TOOLBAR, &w, &h); 141 | else if (strcasecmp (val, "LARGE_TOOLBAR") == 0) 142 | gtk_icon_size_lookup (GTK_ICON_SIZE_LARGE_TOOLBAR, &w, &h); 143 | else if (strcasecmp (val, "DND") == 0) 144 | gtk_icon_size_lookup (GTK_ICON_SIZE_DND, &w, &h); 145 | else if (strcasecmp (val, "DIALOG") == 0) 146 | gtk_icon_size_lookup (GTK_ICON_SIZE_DIALOG, &w, &h); 147 | 148 | if (w && h) 149 | icon_size = MIN (w, h); 150 | } 151 | 152 | static gchar * 153 | parse_font (gchar *fn) 154 | { 155 | gchar **fnt; 156 | gint i = 1; 157 | GString *pfd = g_string_new (NULL); 158 | 159 | fnt = g_strsplit (fn, ":", -1); 160 | 161 | if (g_ascii_strcasecmp (fnt[0], "xft") != 0) 162 | return fnt[0]; 163 | 164 | while (fnt[i]) 165 | { 166 | if (g_ascii_strncasecmp (fnt[i], "style=", 6) == 0) 167 | g_string_append_printf (pfd, "%s ", fnt[i] + 6); 168 | else if (g_ascii_strncasecmp (fnt[i], "size=", 5) == 0) 169 | g_string_append_printf (pfd, "%s ", fnt[i] + 5); 170 | else if (g_ascii_strncasecmp (fnt[i], "pixelsize=", 10) == 0) 171 | g_string_append_printf (pfd, "%spx ", fnt[i] + 10); 172 | else 173 | g_string_append_printf (pfd, "%s ", fnt[i]); 174 | i++; 175 | } 176 | 177 | return pfd->str; 178 | } 179 | 180 | static gint 181 | run_pfd_mode () 182 | { 183 | PangoFontDescription *fnd = NULL; 184 | 185 | if (!args || !args[0]) 186 | { 187 | g_printerr (_("no font specified\n")); 188 | return 1; 189 | } 190 | 191 | /* parse font */ 192 | fnd = pango_font_description_from_string (parse_font (args[0])); 193 | if (!fnd) 194 | { 195 | g_printerr (_("cannot get font description for for string \"%s\"\n"), args[0]); 196 | return 1; 197 | } 198 | 199 | /* print font */ 200 | switch (font_type) 201 | { 202 | case PANGO_SPEC: 203 | g_print ("%s\n", pango_font_description_to_string (fnd)); 204 | break; 205 | case XFT_SPEC: 206 | { 207 | PangoFontMask mask = pango_font_description_get_set_fields (fnd); 208 | 209 | if (mask & PANGO_FONT_MASK_FAMILY) 210 | g_print ("xft:%s", pango_font_description_get_family (fnd)); 211 | else 212 | g_print ("xft:Sans"); /* simple default */ 213 | 214 | if (mask & PANGO_FONT_MASK_WEIGHT) 215 | { 216 | switch (pango_font_description_get_weight (fnd)) 217 | { 218 | case PANGO_WEIGHT_THIN: 219 | g_print (":Thin"); 220 | break; 221 | case PANGO_WEIGHT_ULTRALIGHT: 222 | g_print (":Ultralight"); 223 | break; 224 | case PANGO_WEIGHT_LIGHT: 225 | g_print (":Light"); 226 | break; 227 | case PANGO_WEIGHT_SEMILIGHT: 228 | g_print (":Semilight"); 229 | break; 230 | case PANGO_WEIGHT_BOOK: 231 | g_print (":Book"); 232 | break; 233 | case PANGO_WEIGHT_NORMAL: 234 | break; 235 | case PANGO_WEIGHT_MEDIUM: 236 | g_print (":Medium"); 237 | break; 238 | case PANGO_WEIGHT_SEMIBOLD: 239 | g_print (":Semibold"); 240 | break; 241 | case PANGO_WEIGHT_BOLD: 242 | g_print (":Bold"); 243 | break; 244 | case PANGO_WEIGHT_ULTRABOLD: 245 | g_print (":Ultrabold"); 246 | break; 247 | case PANGO_WEIGHT_HEAVY: 248 | g_print (":Heavy"); 249 | break; 250 | case PANGO_WEIGHT_ULTRAHEAVY: 251 | g_print (":Ultraheavy"); 252 | break; 253 | } 254 | } 255 | 256 | if (mask & PANGO_FONT_MASK_STYLE) 257 | { 258 | switch (pango_font_description_get_style (fnd)) 259 | { 260 | case PANGO_STYLE_NORMAL: 261 | break; 262 | case PANGO_STYLE_OBLIQUE: 263 | g_print (":Oblique"); 264 | break; 265 | case PANGO_STYLE_ITALIC: 266 | g_print (":Italic"); 267 | break; 268 | } 269 | } 270 | 271 | if (mask & PANGO_FONT_MASK_SIZE) 272 | { 273 | if (pango_font_description_get_size_is_absolute (fnd)) 274 | g_print (":pixelsize=%d", pango_font_description_get_size (fnd) / PANGO_SCALE); 275 | else 276 | g_print (":size=%d", pango_font_description_get_size (fnd) / PANGO_SCALE); 277 | } 278 | 279 | g_print ("\n"); 280 | 281 | break; 282 | } 283 | } 284 | 285 | return 0; 286 | } 287 | 288 | static gint 289 | run_icon_mode () 290 | { 291 | GtkIconTheme *theme; 292 | GtkIconInfo *ii; 293 | gchar *output = NULL; 294 | 295 | if (!args || !args[0]) 296 | { 297 | g_printerr (_("no icon specified\n")); 298 | return 1; 299 | } 300 | 301 | if (icon_theme_name) 302 | { 303 | theme = gtk_icon_theme_new (); 304 | gtk_icon_theme_set_custom_theme (theme, icon_theme_name); 305 | } 306 | else 307 | theme = gtk_icon_theme_get_default (); 308 | 309 | if (mime) 310 | { 311 | gchar *ctype = g_content_type_from_mime_type (args[0]); 312 | output = g_content_type_get_generic_icon_name (ctype); 313 | } 314 | else 315 | { 316 | ii = gtk_icon_theme_lookup_icon (theme, args[0], icon_size, 0); 317 | if (ii == NULL) 318 | return 1; 319 | output = (gchar *) gtk_icon_info_get_filename (ii); 320 | } 321 | 322 | if (output) 323 | g_print ("%s\n", output); 324 | else 325 | return 1; 326 | 327 | return 0; 328 | } 329 | 330 | static gint 331 | run_color_mode () 332 | { 333 | if (pick_color) 334 | { 335 | gtk_init (NULL, NULL); 336 | yad_get_screen_color (NULL); 337 | gtk_main (); 338 | } 339 | 340 | return 0; 341 | } 342 | 343 | #ifdef HAVE_SPELL 344 | static gint 345 | show_langs () 346 | { 347 | const GList *lng; 348 | 349 | for (lng = gtk_spell_checker_get_language_list (); lng; lng = lng->next) 350 | g_print ("%s\n", (gchar *) lng->data); 351 | 352 | return 0; 353 | } 354 | #endif 355 | 356 | #ifdef HAVE_SOURCEVIEW 357 | static gint 358 | show_themes () 359 | { 360 | GtkSourceStyleSchemeManager *sm; 361 | const gchar **si; 362 | guint i = 0; 363 | 364 | sm = gtk_source_style_scheme_manager_get_default (); 365 | if ((si = (const gchar **) gtk_source_style_scheme_manager_get_scheme_ids (sm)) == NULL) 366 | return 1; 367 | 368 | while (si[i]) 369 | { 370 | GtkSourceStyleScheme *s = gtk_source_style_scheme_manager_get_scheme (sm, si[i]); 371 | g_print ("%s\n", gtk_source_style_scheme_get_name (s)); 372 | i++; 373 | } 374 | 375 | return 0; 376 | } 377 | #endif 378 | 379 | int 380 | main (int argc, char *argv[]) 381 | { 382 | GOptionContext *ctx; 383 | GOptionGroup *grp; 384 | GError *err = NULL; 385 | gint ret = 0; 386 | 387 | setlocale (LC_ALL, ""); 388 | 389 | #ifdef ENABLE_NLS 390 | bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); 391 | bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); 392 | textdomain (GETTEXT_PACKAGE); 393 | #endif 394 | 395 | gtk_init (&argc, &argv); 396 | 397 | ctx = g_option_context_new (_("- yad miscellaneous tools")); 398 | g_option_context_add_main_entries (ctx, ents, GETTEXT_PACKAGE); 399 | 400 | grp = g_option_group_new ("pfd", _("PFD mode"), _("Show pfd mode options"), NULL, NULL); 401 | g_option_group_add_entries (grp, pfd_ents); 402 | g_option_group_set_translation_domain (grp, GETTEXT_PACKAGE); 403 | g_option_context_add_group (ctx, grp); 404 | 405 | grp = g_option_group_new ("icon", _("Icon mode"), _("Show icon mode options"), NULL, NULL); 406 | g_option_group_add_entries (grp, icon_ents); 407 | g_option_group_set_translation_domain (grp, GETTEXT_PACKAGE); 408 | g_option_context_add_group (ctx, grp); 409 | 410 | grp = g_option_group_new ("color", _("Color mode"), _("Show color mode options"), NULL, NULL); 411 | g_option_group_add_entries (grp, color_ents); 412 | g_option_group_set_translation_domain (grp, GETTEXT_PACKAGE); 413 | g_option_context_add_group (ctx, grp); 414 | 415 | if (!g_option_context_parse (ctx, &argc, &argv, &err)) 416 | { 417 | g_printerr (_("option parsing failed: %s\n"), err->message); 418 | return 1; 419 | } 420 | 421 | if (ver) 422 | { 423 | g_print ("%s (GTK+ %d.%d.%d)\n", PACKAGE_VERSION, gtk_major_version, gtk_minor_version, gtk_micro_version); 424 | return 0; 425 | } 426 | 427 | if (pfd_mode) 428 | ret = run_pfd_mode (); 429 | else if (icon_mode) 430 | ret = run_icon_mode (); 431 | else if (color_mode) 432 | ret = run_color_mode (); 433 | #ifdef HAVE_SPELL 434 | else if (langs_mode) 435 | ret = show_langs (); 436 | #endif 437 | #ifdef HAVE_SOURCEVIEW 438 | else if (themes_mode) 439 | ret = show_themes (); 440 | #endif 441 | else 442 | { 443 | g_printerr (_("no mode specified\n")); 444 | return 1; 445 | } 446 | 447 | return ret; 448 | } 449 | --------------------------------------------------------------------------------