From 151547a99ed142168ec4a11e526102994f6736a9 Mon Sep 17 00:00:00 2001 From: Dave Davenport Date: Fri, 24 Apr 2020 19:54:08 +0200 Subject: [Themes] add calc() support to distance in theme format. (#1105) * Initial test to allow math in distances. Support + and - Needs spaces around + and -. * [THEME] Fix printing theme with math in distance. * [Theme] use calc() syntax. * [Theme] Add * and / to calc(). * [Theme] Fix the precedense ordering in parsing. Also avoid making copies. * [Theme] Don't print unneeded (). * [Theme] Add modulo to calc. --- doc/rofi-script.5 | 12 --- doc/rofi-theme-selector.1 | 4 - doc/rofi-theme.5 | 238 ++++++++++----------------------------------- doc/rofi-theme.5.markdown | 19 ++++ doc/rofi.1 | 64 ------------ include/rofi-types.h | 29 +++++- include/theme.h | 1 + lexer/theme-lexer.l | 11 +++ lexer/theme-parser.y | 134 ++++++++++++++++++++++--- source/theme.c | 211 ++++++++++++++++++++++++++++++++++------ source/widgets/scrollbar.c | 2 +- source/widgets/widget.c | 10 +- 12 files changed, 418 insertions(+), 317 deletions(-) diff --git a/doc/rofi-script.5 b/doc/rofi-script.5 index a2daf9a9..e5fa1b96 100644 --- a/doc/rofi-script.5 +++ b/doc/rofi-script.5 @@ -64,8 +64,6 @@ Rofi sets the following environment variable when executing the script: .SS \fB\fCROFI\_RETV\fR .PP An integer number with the current state: - -.RS .IP \(bu 2 \fB0\fP: Initial call of script. .IP \(bu 2 @@ -75,8 +73,6 @@ An integer number with the current state: .IP \(bu 2 \fB10\-28\fP: Custom keybinding 1\-19 -.RE - .SH Passing mode options .PP Extra options, like setting the prompt, can be set by the script. @@ -96,8 +92,6 @@ For example to set the prompt: .PP The following extra options exists: - -.RS .IP \(bu 2 \fBprompt\fP: Update the prompt text. .IP \(bu 2 @@ -113,8 +107,6 @@ The following extra options exists: .IP \(bu 2 \fBno\-custom\fP: Only accept listed entries, ignore custom input. -.RE - .SH Parsing row options .PP Extra options for individual rows can be set. @@ -134,8 +126,6 @@ For example: .PP The following options are supported: - -.RS .IP \(bu 2 \fBicon\fP: Set the icon for that row. .IP \(bu 2 @@ -143,8 +133,6 @@ The following options are supported: .IP \(bu 2 \fBnonselectable\fP: If true the row cannot activated. -.RE - .SH SEE ALSO .PP rofi(1), rofi\-sensible\-terminal(1), dmenu(1), rofi\-theme(5), rofi\-theme\-selector(1) diff --git a/doc/rofi-theme-selector.1 b/doc/rofi-theme-selector.1 index de076ff4..99525093 100644 --- a/doc/rofi-theme-selector.1 +++ b/doc/rofi-theme-selector.1 @@ -18,8 +18,6 @@ It lets you preview each theme with the Enter key and apply the theme to your .SH Theme directories .PP \fBrofi\-theme\-selector\fP searches the following directories for themes: - -.RS .IP \(bu 2 ${PREFIX}/share/rofi/themes .IP \(bu 2 @@ -27,8 +25,6 @@ $XDG\_CONFIG\_HOME/rofi/themes .IP \(bu 2 $XDG\_DATA\_HOME/share/rofi/themes -.RE - .PP ${PREFIX} reflects the install location of rofi. In most cases this will be "/usr".
$XDG\_CONFIG\_HOME is normally unset. Default path is "$HOME/.config".
diff --git a/doc/rofi-theme.5 b/doc/rofi-theme.5 index 81affdb4..cc0bc564 100644 --- a/doc/rofi-theme.5 +++ b/doc/rofi-theme.5 @@ -19,15 +19,11 @@ preferred. .SH Comments .PP C and C++ file comments are supported. - -.RS .IP \(bu 2 Anything after \fB\fC//\fR and before a newline is considered a comment. .IP \(bu 2 Everything between \fB\fC/*\fR and \fB\fC*/\fR is a comment. -.RE - .PP Comments can be nested and the C comments can be inline. @@ -246,8 +242,6 @@ When used, values with the wrong type that cannot be converted are ignored. .PP The current theme format supports different types: - -.RS .IP \(bu 2 a string .IP \(bu 2 @@ -281,18 +275,12 @@ an environment variable .IP \(bu 2 Inherit -.RE - .PP Some of these types are a combination of other types. -.SH String -.RS -.IP \(bu 2 +.SH String.IP \(bu 2 Format: \fB\fC"[:print:]+"\fR -.RE - .PP A string is always surrounded by double quotes (\fB\fC"\fR). Between the quotes there can be any printable character. @@ -311,13 +299,9 @@ font: "Awasome 12"; .PP The string must be valid UTF\-8. -.SH Integer -.RS -.IP \(bu 2 +.SH Integer.IP \(bu 2 Format: \fB\fC[\-+]?[:digit:]+\fR -.RE - .PP An integer may contain any number. @@ -333,13 +317,9 @@ lines: 12; .fi .RE -.SH Real -.RS -.IP \(bu 2 +.SH Real.IP \(bu 2 Format: \fB\fC[\-+]?[:digit:]+(\\.[:digit:]+)?\fR -.RE - .PP A real is an integer with an optional fraction. @@ -358,13 +338,9 @@ real: 3.4; .PP The following is not valid: \fB\fC\&.3\fR, \fB\fC3.\fR or scientific notation: \fB\fC3.4e\-3\fR\&. -.SH Boolean -.RS -.IP \(bu 2 +.SH Boolean.IP \(bu 2 Format: \fB\fC(true|false)\fR -.RE - .PP Boolean value is either \fB\fCtrue\fR or \fB\fCfalse\fR\&. This is case\-\&sensitive. @@ -383,8 +359,6 @@ dynamic: false; .SH Color .PP \fBrofi\fP supports the color formats as specified in the CSS standard (1,2,3 and some of CSS 4) - -.RS .IP \(bu 2 Format: \fB\fC#{HEX}{3}\fR (rgb) .IP \(bu 2 @@ -406,15 +380,11 @@ Format: \fB\fCcmyk( {PERCENTAGE}, {PERCENTAGE}, {PERCENTAGE}, {PERCENTAGE} [, {P .IP \(bu 2 Format: \fB\fC{named\-color} [ / {PERCENTAGE} ]\fR -.RE - .PP The white\-space format proposed in CSS4 is also supported. .PP The different values are: - -.RS .IP \(bu 2 \fB\fC{HEX}\fR is a hexadecimal number ('0\-9a\-f' case insensitive). .IP \(bu 2 @@ -443,8 +413,6 @@ PapayaWhip, PeachPuff, Peru, Pink, Plum, PowderBlue, Purple, RebeccaPurple, Red, Salmon, SandyBrown, SeaGreen, SeaShell, Sienna, Silver, SkyBlue, SlateBlue, SlateGray, SlateGrey, Snow, SpringGreen, SteelBlue, Tan, Teal, Thistle, Tomato, Turquoise, Violet, Wheat, White, WhiteSmoke, Yellow, YellowGreen,transparent -.RE - .PP For example: @@ -472,18 +440,12 @@ text\-color: Black; .fi .RE -.SH Text style -.RS -.IP \(bu 2 +.SH Text style.IP \(bu 2 Format: \fB\fC(bold|italic|underline|strikethrough|none)\fR -.RE - .PP Text style indicates how the highlighted text is emphasized. \fB\fCNone\fR indicates that no emphasis should be applied. - -.RS .IP \(bu 2 \fB\fCbold\fR: make the text thicker then the surrounding text. .IP \(bu 2 @@ -495,8 +457,6 @@ should be applied. .IP \(bu 2 \fB\fCsmall caps\fR: emphasise the text using capitalization. -.RE - .PP .RS @@ -504,22 +464,16 @@ should be applied. For some reason \fB\fCsmall caps\fR does not work on some systems. .RE -.SH Line style -.RS -.IP \(bu 2 +.SH Line style.IP \(bu 2 Format: \fB\fC(dash|solid)\fR -.RE - .PP Indicates how a line should be drawn. It currently supports: * \fB\fCdash\fR: a dashed line, where the gap is the same width as the dash * \fB\fCsolid\fR: a solid line -.SH Distance -.RS -.IP \(bu 2 +.SH Distance.IP \(bu 2 Format: \fB\fC{Integer}px\fR .IP \(bu 2 Format: \fB\fC{Real}em\fR @@ -528,12 +482,8 @@ Format: \fB\fC{Real}ch\fR .IP \(bu 2 Format: \fB\fC{Real}%\fR -.RE - .PP A distance can be specified in 3 different units: - -.RS .IP \(bu 2 \fB\fCpx\fR: Screen pixels. .IP \(bu 2 @@ -543,8 +493,6 @@ A distance can be specified in 3 different units: .IP \(bu 2 \fB\fC%\fR: Percentage of the \fBmonitor\fP size. -.RE - .PP Distances used in the horizontal direction use the monitor width. Distances in the vertical direction use the monitor height. @@ -563,9 +511,36 @@ For example: On a full\-HD (1920x1080) monitor, it defines a padding of 192 pixels on the left and right side and 108 pixels on the top and bottom. -.SH Padding +.SS Calculating sizes +.PP +Rofi supports some maths in calculating sizes. For this it uses the CSS syntax: + +.PP .RS + +.nf +width: calc( 100% \- 37px ); + +.fi +.RE + +.PP +It supports the following operations: +.IP \(bu 2 +\fB\fC+\fR: Add +.IP \(bu 2 +\fB\fC\-\fR: Subtract +.IP \(bu 2 +\fB\fC/\fR: Divide .IP \(bu 2 +\fB\fC*\fR: Multiply +.IP \(bu 2 +\fB\fC%\fR: Multiply + +.PP +It uses the C precedence ordering. + +.SH Padding.IP \(bu 2 Format: \fB\fC{Integer}\fR .IP \(bu 2 Format: \fB\fC{Distance}\fR @@ -576,15 +551,11 @@ Format: \fB\fC{Distance} {Distance} {Distance}\fR .IP \(bu 2 Format: \fB\fC{Distance} {Distance} {Distance} {Distance}\fR -.RE - .PP If no unit is specified, pixels are assumed. .PP The different number of fields in the formats are parsed like: - -.RS .IP \(bu 2 1 field: \fB\fCall\fR .IP \(bu 2 @@ -594,11 +565,7 @@ The different number of fields in the formats are parsed like: .IP \(bu 2 4 fields: \fB\fCtop\fR, \fB\fCright\fR, \fB\fCbottom\fR, \fB\fCleft\fR -.RE - -.SH Border -.RS -.IP \(bu 2 +.SH Border.IP \(bu 2 Format: \fB\fC{Integer}\fR .IP \(bu 2 Format: \fB\fC{Distance}\fR @@ -617,8 +584,6 @@ Format: \fB\fC{Distance} {Line style} {Distance} {Line style} {Distance} {Line s .IP \(bu 2 Format: \fB\fC{Distance} {Line style} {Distance} {Line style} {Distance} {Line style} {Distance} {Line style}\fR -.RE - .PP Borders are identical to padding, except that each distance field has a line style property. @@ -633,12 +598,9 @@ When no unit is specified, pixels are assumed. .SH Position .PP Indicate a place on the window/monitor. - -.RS .IP \(bu 2 - -.PP Format: \fB\fC(center|east|north|west|south|north east|north west|south west|south east)\fR + .PP .RS @@ -646,15 +608,13 @@ Format: \fB\fC(center|east|north|west|south|north east|north west|south west|sou north west | north | north east \-\-\-\-\-\-\-\-\-\-\-\-\-|\-\-\-\-\-\-\-\-\-\-\-\-\-|\-\-\-\-\-\-\-\-\-\-\-\- - west | center | east + west | center | east \-\-\-\-\-\-\-\-\-\-\-\-\-|\-\-\-\-\-\-\-\-\-\-\-\-\-|\-\-\-\-\-\-\-\-\-\-\-\- south west | south | south east .fi .RE -.RE - .SH Visibility .PP It is possible to hide widgets: @@ -664,13 +624,9 @@ inputbar { enabled: false; } -.SH Reference -.RS -.IP \(bu 2 +.SH Reference.IP \(bu 2 Format: \fB\fC@{PROPERTY NAME}\fR -.RE - .PP A reference can point to another reference. Currently, the maximum number of redirects is 20. A property always refers to another property. It cannot be used for a subpart of the property. @@ -703,34 +659,22 @@ window { .fi .RE -.SH Orientation -.RS -.IP \(bu 2 +.SH Orientation.IP \(bu 2 Format: \fB\fC(horizontal|vertical)\fR -.RE - .PP Specify the orientation of the widget. -.SH List of keywords -.RS -.IP \(bu 2 +.SH List of keywords.IP \(bu 2 Format: \fB\fC[ keyword, keyword ]\fR -.RE - .PP A list starts with a '[' and ends with a ']'. The entries in the list are comma\-separated. The \fB\fCkeyword\fR in the list refers to an widget name. -.SH Environment variable -.RS -.IP \(bu 2 +.SH Environment variable.IP \(bu 2 Format: \fB\fC${:alnum:}\fR -.RE - .PP This will parse the environment variable as the property value. (that then can be any of the above types). The environment variable should be an alphanumeric string without white\-space. @@ -746,13 +690,9 @@ The environment variable should be an alphanumeric string without white\-space. .fi .RE -.SH Inherit -.RS -.IP \(bu 2 +.SH Inherit.IP \(bu 2 Format: \fB\fCinherit\fR -.RE - .PP Inherits the property from its parent widget. @@ -809,20 +749,14 @@ element selected { .SH Name .PP The current widgets available in \fBrofi\fP: - -.RS .IP \(bu 2 \fB\fCwindow\fR - -.RS .IP \(bu 2 \fB\fCoverlay\fR: the overlay widget. .IP \(bu 2 \fB\fCmainbox\fR: The mainbox box. .IP \(bu 2 \fB\fCinputbar\fR: The input bar box. - -.RS .IP \(bu 2 \fB\fCbox\fR: the horizontal @box packing the widgets .IP \(bu 2 @@ -835,49 +769,27 @@ The current widgets available in \fBrofi\fP: \fB\fCnum\-rows\fR: Shows the total number of rows. .IP \(bu 2 \fB\fCnum\-filtered\-rows\fR: Shows the total number of rows after filtering. - -.RE .IP \(bu 2 \fB\fClistview\fR: The listview. - -.RS .IP \(bu 2 \fB\fCscrollbar\fR: the listview scrollbar .IP \(bu 2 \fB\fCelement\fR: a box in the listview holding the entries - -.RS .IP \(bu 2 \fB\fCelement\-icon\fR: the widget in the listview's entry showing the (optional) icon .IP \(bu 2 \fB\fCelement\-index\fR: the widget in the listview's entry keybindable index (1,2,3..0) .IP \(bu 2 \fB\fCelement\-text\fR: the widget in the listview's entry showing the text. - -.RE - -.RE .IP \(bu 2 \fB\fCmode\-switcher\fR: the main horizontal @box packing the buttons. - -.RS .IP \(bu 2 \fB\fCbutton\fR: the buttons @textbox for each mode - -.RE .IP \(bu 2 \fB\fCmessage\fR: The container holding the textbox. - -.RS .IP \(bu 2 \fB\fCtextbox\fR: the message textbox -.RE - -.RE - -.RE - .PP Note that these path names match the default theme. Themes that provide a custom layout will have different elements, and structure. @@ -949,9 +861,7 @@ This allows the colors used for drawing the handle to be set independently. .PP The following properties are currently supported: -.SS all widgets: -.RS -.IP \(bu 2 +.SS all widgets:.IP \(bu 2 \fBenabled\fP: enable/disable the widget .IP \(bu 2 \fBpadding\fP: padding @@ -972,11 +882,7 @@ Background color \fBborder\-color\fP: color Color of the border -.RE - -.SS window: -.RS -.IP \(bu 2 +.SS window:.IP \(bu 2 .PP \fBfont\fP: string @@ -1020,11 +926,7 @@ The width of the window \fBy\-offset\fP: distance The offset of the window to the anchor point, allowing you to push the window left/right/up/down -.RE - -.SS scrollbar: -.RS -.IP \(bu 2 +.SS scrollbar:.IP \(bu 2 \fBbackground\-color\fP: color .IP \(bu 2 \fBhandle\-width\fP: distance @@ -1033,22 +935,14 @@ The offset of the window to the anchor point, allowing you to push the window le .IP \(bu 2 \fBborder\-color\fP: color -.RE - -.SS box: -.RS -.IP \(bu 2 +.SS box:.IP \(bu 2 \fBorientation\fP: orientation Set the direction the elements are packed. .IP \(bu 2 \fBspacing\fP: distance Distance between the packed elements. -.RE - -.SS textbox: -.RS -.IP \(bu 2 +.SS textbox:.IP \(bu 2 \fBbackground\-color\fP: color .IP \(bu 2 \fBborder\-color\fP: the color used for the border around the widget. @@ -1076,11 +970,7 @@ color is optional, multiple highlight styles can be added like: bold underline i .IP \(bu 2 \fBblink\fP: Enable/Disable blinking on an input textbox (Boolean). -.RE - -.SS listview: -.RS -.IP \(bu 2 +.SS listview:.IP \(bu 2 \fBcolumns\fP: integer Number of columns to show (at least 1) .IP \(bu 2 @@ -1114,8 +1004,6 @@ Reverse the ordering (top down to bottom up). \fBfixed\-columns\fP: boolean Do not reduce the number of columns shown when number of visible elements is not enough to fill them all. -.RE - .PP Each element is a \fB\fCbox\fR called \fB\fCelement\fR\&. Each \fB\fCelement\fR can contain an \fB\fCelement\-icon\fR and \fB\fCelement\-text\fR\&. @@ -1207,8 +1095,6 @@ The layout of \fBrofi\fP can be tweaked by packing the 'fixed' widgets in a cust .PP The following widgets are fixed, as they provide core \fBrofi\fP functionality: - -.RS .IP \(bu 2 prompt .IP \(bu 2 @@ -1228,13 +1114,9 @@ num\-rows .IP \(bu 2 num\-filtered\-rows -.RE - .PP The following keywords are defined and can be used to automatically pack a subset of the widgets. These are used in the default theme as depicted in the figure above. - -.RS .IP \(bu 2 mainbox Packs: \fB\fCinputbar, message, listview, mode\-switcher\fR @@ -1242,15 +1124,11 @@ Packs: \fB\fCinputbar, message, listview, mode\-switcher\fR inputbar Packs: \fB\fCprompt,entry,case\-indicator\fR -.RE - .PP Any widget name starting with \fB\fCtextbox\fR is a textbox widget, others are box widgets and can pack other widgets. .PP There are several special widgets that can be used by prefixing the name of the widget: - -.RS .IP \(bu 2 \fB\fCtextbox\fR: This is a textbox widget. The displayed string can be set with \fB\fCstr\fR\&. @@ -1266,8 +1144,6 @@ The \fB\fCaction\fR can be set to: \fB\fCok|alternate\fR: accept entry and launch alternate action (for run launch in terminal). \fB\fCcustom|alternate\fR: accept custom input and launch alternate action. -.RE - .PP To specify children, set the \fB\fCchildren\fR property (this always happens on the \fB\fCbox\fR child, see example below): @@ -1358,8 +1234,6 @@ Just like CSS, \fBrofi\fP uses the box model for each widget. .PP Explanation of the different parts: - -.RS .IP \(bu 2 Content \- The content of the widget. .IP \(bu 2 @@ -1372,8 +1246,6 @@ The border use the border\-color of the widget. Margin \- Clears an area outside the border. The margin is transparent. -.RE - .PP The box model allows us to add a border around elements, and to define space between elements. @@ -1498,8 +1370,6 @@ Parts of the theme can be conditionally loaded, like the CSS \fB\fC@media\fR opt .PP It supports the following keys as constraint: - -.RS .IP \(bu 2 \fB\fCmin\-width\fR: load when width is bigger then value. .IP \(bu 2 @@ -1515,21 +1385,15 @@ It supports the following keys as constraint: .IP \(bu 2 \fB\fCmonitor\-id\fR: The monitor id, see rofi \-help for id's. -.RE - .SH Multiple file handling .PP The rasi file format offers two methods of including other files. This can be used to modify existing themes, or have multiple variations on a theme. - -.RS .IP \(bu 2 import: Import and parse a second file. .IP \(bu 2 theme: Discard theme, and load file as a fresh theme. -.RE - .PP Syntax: @@ -1548,8 +1412,6 @@ The specified file can either by \fIname\fP, \fIfilename\fP,\fIfull path\fP\&. .PP If a filename is provided, it will try to resolve it in the following order: - -.RS .IP \(bu 2 \fB\fC${XDG\_CONFIG\_HOME}/rofi/themes/\fR .IP \(bu 2 @@ -1559,8 +1421,6 @@ If a filename is provided, it will try to resolve it in the following order: .IP \(bu 2 \fB\fC${INSTALL PREFIX}/share/rofi/themes/\fR -.RE - .PP A name is resolved as a filename by appending the \fB\fC\&.rasi\fR extension. diff --git a/doc/rofi-theme.5.markdown b/doc/rofi-theme.5.markdown index 0813f8c9..143551db 100644 --- a/doc/rofi-theme.5.markdown +++ b/doc/rofi-theme.5.markdown @@ -352,6 +352,24 @@ For example: On a full-HD (1920x1080) monitor, it defines a padding of 192 pixels on the left and right side and 108 pixels on the top and bottom. +### Calculating sizes + +Rofi supports some maths in calculating sizes. For this it uses the CSS syntax: + +``` +width: calc( 100% - 37px ); +``` + +It supports the following operations: + +* `+`: Add +* `-`: Subtract +* `/`: Divide +* `*`: Multiply +* `%`: Multiply + +It uses the C precedence ordering. + ## Padding * Format: `{Integer}` @@ -837,6 +855,7 @@ element selected { } ``` + ### Padding and margin Just like CSS, **rofi** uses the box model for each widget. diff --git a/doc/rofi.1 b/doc/rofi.1 index 1cdd8bf0..db6c9640 100644 --- a/doc/rofi.1 +++ b/doc/rofi.1 @@ -68,8 +68,6 @@ Markup support can be enabled, see CONFIGURATION options. .SH CONFIGURATION .PP There are currently three methods of setting configuration options (evaluated in order below): - -.RS .IP \(bu 2 System configuration file (for example \fB\fC/etc/rofi.rasi\fR or old format \fB\fC/etc/rofi.conf\fR). It first checks XDG\_CONFIG\_DIRS and then SYSCONFDIR (that is passed at compile time). @@ -88,8 +86,6 @@ This is the recommended way of configuring \fBrofi\fP\&. .IP \(bu 2 Command\-line options: Arguments passed to \fBrofi\fP\&. -.RE - .PP \fBTIP\fP: To get a template config file run: \fB\fCrofi \-dump\-xresources > rofi\-example.config\fR\&. \fBNOTE\fP: In version 1.4.0 we support configuration in a new format, a config for this can be generated by: \fB\fCrofi @@ -135,8 +131,6 @@ rofi \-dump\-xresources .PP The configuration system supports the following types: - -.RS .IP \(bu 2 string .IP \(bu 2 @@ -146,8 +140,6 @@ char .IP \(bu 2 Boolean -.RE - .PP Boolean options have a non\-default command\-line syntax. Example to enable option X: @@ -195,8 +187,6 @@ This does not validate all passed values (for example, colors). .PP Specify the number of threads \fBrofi\fP should use: - -.RS .IP \(bu 2 0: Autodetect the number of supported hardware threads. .IP \(bu 2 @@ -204,8 +194,6 @@ Specify the number of threads \fBrofi\fP should use: .IP \(bu 2 2..N: Specify the maximum number of threads to use in the thread pool. -.RE - .PP \fB\fC\-dmenu\fR @@ -392,8 +380,6 @@ fallback themes. .PP Specify the matching algorithm used. Current the following methods are supported. - -.RS .IP \(bu 2 \fBnormal\fP: match the int string .IP \(bu 2 @@ -403,8 +389,6 @@ Current the following methods are supported. .IP \(bu 2 \fBfuzzy\fP: do a fuzzy match -.RE - .PP Default: \fInormal\fP @@ -429,8 +413,6 @@ Only show desktop files that are present in the listed categories. .PP When using drun, match only with the specified Desktop entry fields. The different fields are: - -.RS .IP \(bu 2 \fBname\fP: the application's name .IP \(bu 2 @@ -448,15 +430,11 @@ The different fields are: .PP Default: \fIname,generic,exec,categories,keywords\fP -.RE - .PP \fB\fC\-drun\-display\-format\fR .PP The format string for the drun dialog: - -.RS .IP \(bu 2 \fBname\fP: the application's name .IP \(bu 2 @@ -468,8 +446,6 @@ The format string for the drun dialog: .IP \(bu 2 \fBcomment\fP: the application comment -.RE - .PP Pango markup can be used to formatting the output. @@ -506,8 +482,6 @@ Default: false .PP When using window mode, match only with the specified fields. The different fields are: - -.RS .IP \(bu 2 \fBtitle\fP: window's title .IP \(bu 2 @@ -525,8 +499,6 @@ The different fields are: .PP Default: \fIall\fP -.RE - .PP \fB\fC\-matching\-negate\-char\fR \fIchar\fP @@ -716,8 +688,6 @@ When one entry is left, automatically select it. Select monitor to display \fBrofi\fP on. It accepts as input: \fIprimary\fP (if primary output is set), the \fIxrandr\fP output name, or integer number (in order of detection). Negative numbers are handled differently: - -.RS .IP \(bu 2 \fB\-1\fP: the currently focused monitor. .IP \(bu 2 @@ -734,8 +704,6 @@ behavior.) .PP Default: \fI\-5\fP -.RE - .PP See \fB\fCrofi \-h\fR output for the detected monitors, their position, and size. @@ -886,8 +854,6 @@ Format what is being displayed for windows. .PP \fIfield\fP: - -.RS .IP \(bu 2 \fBw\fP: desktop name .IP \(bu 2 @@ -899,8 +865,6 @@ Format what is being displayed for windows. .IP \(bu 2 \fBc\fP: class -.RE - .PP \fIlen\fP: maximum field length (0 for auto\-size). If length and window \fIwidth\fP are negative, field length is \fIwidth \- len\fP\&. if length is positive, the entry will be truncated or padded to fill that length. @@ -961,15 +925,11 @@ This setting can be changed at runtime (see \fB\fC\-kb\-toggle\-sort\fR). .PP There are 2 sorting method: - -.RS .IP \(bu 2 levenshtein (Default) .IP \(bu 2 fzf sorting. -.RE - .SS Dmenu specific .PP \fB\fC\-sep\fR \fIseparator\fP @@ -1033,8 +993,6 @@ Makes dmenu searches case\-insensitive .PP Active row, mark \fIX\fP as active. Where \fIX\fP is a comma\-separated list of python(1)\-style indices and ranges, e.g. indices start at 0, \-1 refers to the last row with \-2 preceding it, ranges are left\-open and right\-close, and so on. You can specify: - -.RS .IP \(bu 2 A single row: '5' .IP \(bu 2 @@ -1046,8 +1004,6 @@ A set of rows: '2,0,\-9' .IP \(bu 2 Or any combination: '5,\-3:,7:11,2,0,\-9' -.RE - .PP \fB\fC\-u\fR \fIX\fP @@ -1073,8 +1029,6 @@ This mode returns directly when no entries given. .PP Allows the output of dmenu to be customized (N is the total number of input entries): - -.RS .IP \(bu 2 \&'s' selected string .IP \(bu 2 @@ -1090,8 +1044,6 @@ Allows the output of dmenu to be customized (N is the total number of input entr .IP \(bu 2 \&'F' quoted filter string (user input) -.RE - .PP Default: 's' @@ -1280,8 +1232,6 @@ For more information on debugging, see the wiki .SH PATTERN .PP To launch commands (for example, when using the ssh launcher), the user can enter the used command\-line. The following keys can be used that will be replaced at runtime: - -.RS .IP \(bu 2 \fB\fC{host}\fR: the host to connect to .IP \(bu 2 @@ -1293,8 +1243,6 @@ To launch commands (for example, when using the ssh launcher), the user can ente .IP \(bu 2 \fB\fC{window}\fR: the window ID of the selected window (in \fB\fCwindow\-command\fR) -.RE - .SH DMENU REPLACEMENT .PP If \fB\fCargv[0]\fR (calling command) is dmenu, \fBrofi\fP will start in dmenu mode. @@ -1317,8 +1265,6 @@ manual. .PP The theme setup allows you to specify colors per state, similar to \fBi3\fP Currently 3 states exist: - -.RS .IP \(bu 2 \fBnormal\fP: normal row .IP \(bu 2 @@ -1326,12 +1272,8 @@ Currently 3 states exist: .IP \(bu 2 \fBactive\fP: highlighted row (active) -.RE - .PP For each state, the following 5 colors must be set: - -.RS .IP \(bu 2 \fBbg\fP: background color row .IP \(bu 2 @@ -1343,8 +1285,6 @@ For each state, the following 5 colors must be set: .IP \(bu 2 \fBhlbg\fP: background color selected row -.RE - .PP The window background and border color should be specified separately. The key \fB\fCcolor\-window\fR contains a tuple \fB\fCbackground,border,separator\fR\&. @@ -1430,8 +1370,6 @@ of the window will be visible through it. .SH KEY BINDINGS .PP \fBrofi\fP has the following key bindings: - -.RS .IP \(bu 2 \fB\fCCtrl\-v, Insert\fR: Paste from clipboard .IP \(bu 2 @@ -1497,8 +1435,6 @@ of the window will be visible through it. .IP \(bu 2 \fB\fCAlt\-Shift\-S\fR: Take a screenshot and store it in the Pictures directory. -.RE - .PP To get a full list of key bindings on the commandline, see \fB\fCrofi \-h\fR\&. The options starting with \fB\fC\-kb\fR are keybindings. diff --git a/include/rofi-types.h b/include/rofi-types.h index bb294dad..ced7e321 100644 --- a/include/rofi-types.h +++ b/include/rofi-types.h @@ -89,12 +89,39 @@ typedef enum /** * Structure representing a distance. */ -typedef struct +typedef enum +{ + ROFI_DISTANCE_MODIFIER_NONE, + ROFI_DISTANCE_MODIFIER_ADD, + ROFI_DISTANCE_MODIFIER_SUBTRACT, + ROFI_DISTANCE_MODIFIER_DIVIDE, + ROFI_DISTANCE_MODIFIER_MULTIPLY, + ROFI_DISTANCE_MODIFIER_MODULO, + ROFI_DISTANCE_MODIFIER_GROUP, +} RofiDistanceModifier; + +typedef struct RofiDistanceUnit { /** Distance */ double distance; /** Unit type of the distance */ RofiPixelUnit type; + + /** Type */ + RofiDistanceModifier modtype; + + /** Modifier */ + struct RofiDistanceUnit *left; + + /** Modifier */ + struct RofiDistanceUnit *right; + +} RofiDistanceUnit; + +typedef struct +{ + /** Base */ + RofiDistanceUnit base; /** Style of the line (optional)*/ RofiLineStyle style; } RofiDistance; diff --git a/include/theme.h b/include/theme.h index 0ed71460..055bea71 100644 --- a/include/theme.h +++ b/include/theme.h @@ -387,4 +387,5 @@ void rofi_theme_parse_merge_widgets ( ThemeWidget *parent, ThemeWidget *child ); * Returns the media type described by type. */ ThemeMediaType rofi_theme_parse_media_type ( const char *type ); +RofiDistance rofi_theme_property_copy_distance ( RofiDistance const distance ); #endif diff --git a/lexer/theme-lexer.l b/lexer/theme-lexer.l index 50a2c4e7..ec1ccc0b 100644 --- a/lexer/theme-lexer.l +++ b/lexer/theme-lexer.l @@ -183,6 +183,11 @@ ASTERIX \* ENV $\{[[:alnum:]]*\} +MODIFIER_ADD \+ +MODIFIER_SUBTRACT - +MODIFIER_DIVIDE \/ +MODIFIER_MULTIPLY \* + /* Position */ CENTER (?i:center) NORTH (?i:north) @@ -224,6 +229,7 @@ COLOR_TRANSPARENT (?i:transparent) S_T_PARENT_LEFT \( S_T_PARENT_RIGHT \) +CALC (?i:calc) COMMA , FORWARD_SLASH \/ @@ -450,6 +456,11 @@ if ( queue == NULL ){ {LS_DASH} { return T_DASH; } {INHERIT} { return T_INHERIT; } +{MODIFIER_ADD} { return T_MODIFIER_ADD; } +{MODIFIER_SUBTRACT} { return T_MODIFIER_SUBTRACT; } +{MODIFIER_MULTIPLY} { return T_MODIFIER_MULTIPLY; } +{MODIFIER_DIVIDE} { return T_MODIFIER_DIVIDE; } +{CALC} { return T_CALC; } {ENV} { yytext[yyleng-1] = '\0'; diff --git a/lexer/theme-parser.y b/lexer/theme-parser.y index c85a5bbe..c93e8c7f 100644 --- a/lexer/theme-parser.y +++ b/lexer/theme-parser.y @@ -146,6 +146,7 @@ static ThemeColor hwb_to_rgb ( double h, double w, double b) Property *property; GHashTable *property_list; RofiDistance distance; + RofiDistanceUnit *distance_unit; } %token T_END 0 "end of file" @@ -210,6 +211,13 @@ static ThemeColor hwb_to_rgb ( double h, double w, double b) %token T_LIST_OPEN "List open ('[')" %token T_LIST_CLOSE "List close (']')" +%token T_MODIFIER_ADD "Add ('+')" +%token T_MODIFIER_SUBTRACT "Subtract ('-')" +%token T_MODIFIER_DIVIDE "Divide ('/')" +%token T_MODIFIER_MULTIPLY "Multiply ('*')" + +%token T_CALC "calc" + %token T_BOPEN "bracket open ('{')" %token T_BCLOSE "bracket close ('}')" %token T_PSEP "property separator (':')" @@ -251,6 +259,9 @@ static ThemeColor hwb_to_rgb ( double h, double w, double b) %type t_property_name %type t_property_distance %type t_property_distance_zero +%type t_property_distance_unit_math +%type t_property_distance_unit_math2 +%type t_property_distance_unit %type t_property_unit %type t_property_position %type t_property_position_ew @@ -377,7 +388,7 @@ t_name_prefix_optional t_entry_name_path_selectors T_BOPEN t_property_list_optio gchar *name = g_strdup_printf("@media ( %s: %d )",$3, $5); ThemeWidget *widget = rofi_theme_find_or_create_name ( rofi_theme, name ); widget->set = TRUE; - widget->media = g_malloc0(sizeof(ThemeMedia)); + widget->media = g_slice_new0(ThemeMedia); widget->media->type = rofi_theme_parse_media_type ( $3 ); widget->media->value = (double)$5; for ( unsigned int i = 0; i < $8->num_widgets;i++) { @@ -390,7 +401,7 @@ t_name_prefix_optional t_entry_name_path_selectors T_BOPEN t_property_list_optio gchar *name = g_strdup_printf("@media ( %s: %f )",$3, $5); ThemeWidget *widget = rofi_theme_find_or_create_name ( rofi_theme, name ); widget->set = TRUE; - widget->media = g_malloc0(sizeof(ThemeMedia)); + widget->media = g_slice_new0(ThemeMedia); widget->media->type = rofi_theme_parse_media_type ( $3 ); widget->media->value = $5; for ( unsigned int i = 0; i < $8->num_widgets;i++) { @@ -403,7 +414,7 @@ t_name_prefix_optional t_entry_name_path_selectors T_BOPEN t_property_list_optio gchar *name = g_strdup_printf("@media ( %s: %d px )",$3, $5); ThemeWidget *widget = rofi_theme_find_or_create_name ( rofi_theme, name ); widget->set = TRUE; - widget->media = g_malloc0(sizeof(ThemeMedia)); + widget->media = g_slice_new0(ThemeMedia); widget->media->type = rofi_theme_parse_media_type ( $3 ); widget->media->value = (double)$5; for ( unsigned int i = 0; i < $9->num_widgets;i++) { @@ -503,15 +514,15 @@ t_property_element } | t_property_distance { $$ = rofi_theme_property_create ( P_PADDING ); - $$->value.padding = (RofiPadding){ $1, $1, $1, $1 }; + $$->value.padding = (RofiPadding){ $1, rofi_theme_property_copy_distance($1), rofi_theme_property_copy_distance($1), rofi_theme_property_copy_distance($1) }; } | t_property_distance_zero t_property_distance_zero { $$ = rofi_theme_property_create ( P_PADDING ); - $$->value.padding = (RofiPadding){ $1, $2, $1, $2 }; + $$->value.padding = (RofiPadding){ $1, $2, rofi_theme_property_copy_distance($1), rofi_theme_property_copy_distance($2) }; } | t_property_distance_zero t_property_distance_zero t_property_distance_zero { $$ = rofi_theme_property_create ( P_PADDING ); - $$->value.padding = (RofiPadding){ $1, $2, $3, $2 }; + $$->value.padding = (RofiPadding){ $1, $2, $3, rofi_theme_property_copy_distance($2) }; } | t_property_distance_zero t_property_distance_zero t_property_distance_zero t_property_distance_zero { $$ = rofi_theme_property_create ( P_PADDING ); @@ -599,25 +610,124 @@ t_property_highlight_style t_property_distance_zero : T_INT t_property_line_style { - $$.distance = (double) $1; - $$.type = ROFI_PU_PX; + $$.base.distance = (double) $1; + $$.base.type = ROFI_PU_PX; + $$.base.left = NULL; + $$.base.right = NULL; + $$.base.modtype = ROFI_DISTANCE_MODIFIER_NONE; $$.style = $2; } | t_property_distance { $$ = $1;} ; + /** Distance. */ +t_property_distance_unit +: T_INT t_property_unit { + $$ = g_slice_new0(RofiDistanceUnit); + $$->distance = (double)$1; + $$->type = $2; + $$->left = NULL; + $$->right = NULL; + $$->modtype = ROFI_DISTANCE_MODIFIER_NONE; +} +| T_INT { + $$ = g_slice_new0(RofiDistanceUnit); + $$->distance = (double)$1; + $$->type = ROFI_PU_PX; + $$->left = NULL; + $$->right = NULL; + $$->modtype = ROFI_DISTANCE_MODIFIER_NONE; +} +| T_DOUBLE t_property_unit { + $$ = g_slice_new0(RofiDistanceUnit); + $$->distance = (double)$1; + $$->type = $2; + $$->left = NULL; + $$->right = NULL; + $$->modtype = ROFI_DISTANCE_MODIFIER_NONE; +} +| T_PARENT_LEFT t_property_distance_unit_math2 T_PARENT_RIGHT { + $$ = g_slice_new0(RofiDistanceUnit); + $$->distance = 0; + $$->type = ROFI_DISTANCE_MODIFIER_NONE; + $$->left = $2; + $$->right = 0; + $$->modtype = ROFI_DISTANCE_MODIFIER_GROUP; +}; + + +/** + * Multiply/divide with auto-grouping. + */ +t_property_distance_unit_math +: t_property_distance_unit_math T_MODIFIER_MULTIPLY t_property_distance_unit { + $$ = g_slice_new0(RofiDistanceUnit); + $$->left = $1; + $$->right = $3; + $$->modtype = ROFI_DISTANCE_MODIFIER_MULTIPLY; +} +| t_property_distance_unit_math T_MODIFIER_DIVIDE t_property_distance_unit { + $$ = g_slice_new0(RofiDistanceUnit); + $$->left = $1; + $$->right = $3; + $$->modtype = ROFI_DISTANCE_MODIFIER_DIVIDE; +} +| t_property_distance_unit_math T_PERCENT t_property_distance_unit { + $$ = g_slice_new0(RofiDistanceUnit); + $$->left = $1; + $$->right = $3; + $$->modtype = ROFI_DISTANCE_MODIFIER_MODULO; +} +| t_property_distance_unit { + $$ = $1; +}; + + +/** Level 2 (+-)*/ +t_property_distance_unit_math2 +: t_property_distance_unit_math2 T_MODIFIER_ADD t_property_distance_unit_math { + $$ = g_slice_new0(RofiDistanceUnit); + $$->left = $1; + $$->right = $3; + $$->modtype = ROFI_DISTANCE_MODIFIER_ADD; +} +| t_property_distance_unit_math2 T_MODIFIER_SUBTRACT t_property_distance_unit_math { + $$ = g_slice_new0(RofiDistanceUnit); + $$->left = $1; + $$->right = $3; + $$->modtype = ROFI_DISTANCE_MODIFIER_SUBTRACT; +} +| t_property_distance_unit_math { + $$ = $1; +}; + + t_property_distance /** Integer unit and line style */ : T_INT t_property_unit t_property_line_style { - $$.distance = (double)$1; - $$.type = $2; + $$.base.distance = (double)$1; + $$.base.type = $2; + $$.base.left = NULL; + $$.base.right = NULL; + $$.base.modtype = ROFI_DISTANCE_MODIFIER_NONE; $$.style = $3; } /** Double unit and line style */ | T_DOUBLE t_property_unit t_property_line_style { - $$.distance = (double)$1; - $$.type = $2; + $$.base.distance = (double)$1; + $$.base.type = $2; + $$.base.modtype = ROFI_DISTANCE_MODIFIER_NONE; + $$.base.left = NULL; + $$.base.right = NULL; $$.style = $3; +} +| T_CALC T_PARENT_LEFT t_property_distance_unit_math2 T_PARENT_RIGHT t_property_line_style { + $$.base.distance = 0; + $$.base.type = ROFI_DISTANCE_MODIFIER_NONE; + $$.base.left = $3; + $$.base.right = NULL; + $$.base.modtype = ROFI_DISTANCE_MODIFIER_GROUP; + $$.style = $5; }; /** distance unit. px, em, % */ diff --git a/source/theme.c b/source/theme.c index 069b9ef3..85bf7c86 100644 --- a/source/theme.c +++ b/source/theme.c @@ -47,7 +47,8 @@ void yyerror ( YYLTYPE *yylloc, const char *, const char * ); static gboolean distance_compare ( RofiDistance d, RofiDistance e ) { - return d.type == e.type && d.distance == e.distance && d.style == e.style; + // TODO UPDATE + return d.base.type == e.base.type && d.base.distance == e.base.distance && d.style == e.style; } static gpointer rofi_g_list_strdup ( gconstpointer data, G_GNUC_UNUSED gpointer user_data ) @@ -80,6 +81,33 @@ Property *rofi_theme_property_create ( PropertyType type ) retv->type = type; return retv; } + +static RofiDistanceUnit *rofi_theme_property_copy_distance_unit ( RofiDistanceUnit *unit ) +{ + RofiDistanceUnit *retv = g_slice_new0( RofiDistanceUnit ); + *retv = *unit; + if ( unit->left ) { + retv->left = rofi_theme_property_copy_distance_unit ( unit->left ); + } + if ( unit->right ) { + retv->right = rofi_theme_property_copy_distance_unit ( unit->right ); + } + return retv; +} +RofiDistance rofi_theme_property_copy_distance ( RofiDistance const distance ) +{ + RofiDistance retv = distance; + if ( distance.base.left ) + { + retv.base.left = rofi_theme_property_copy_distance_unit ( distance.base.left ); + } + if ( distance.base.right ) + { + retv.base.right = rofi_theme_property_copy_distance_unit ( distance.base.right ); + } + return retv; +} + Property* rofi_theme_property_copy ( Property *p ) { Property *retv = rofi_theme_property_create ( p->type ); @@ -100,12 +128,45 @@ Property* rofi_theme_property_copy ( Property *p ) retv->value.link.def_value = rofi_theme_property_copy ( p->value.link.def_value ); } break; + case P_PADDING: + { + retv->value = p->value; + retv->value.padding.top = rofi_theme_property_copy_distance ( p->value.padding.top); + retv->value.padding.left = rofi_theme_property_copy_distance ( p->value.padding.left); + retv->value.padding.bottom = rofi_theme_property_copy_distance ( p->value.padding.bottom); + retv->value.padding.right = rofi_theme_property_copy_distance ( p->value.padding.right); + break; + } default: retv->value = p->value; } return retv; } +static void rofi_theme_distance_unit_property_free ( RofiDistanceUnit *unit ) +{ + if ( unit->left ) { + rofi_theme_distance_unit_property_free ( unit->left ); + unit->left = NULL; + } + if ( unit->right ) { + rofi_theme_distance_unit_property_free ( unit->right ); + unit->right = NULL; + } + g_slice_free ( RofiDistanceUnit, unit); +} +static void rofi_theme_distance_property_free ( RofiDistance *distance ) +{ + if ( distance->base.left ) { + rofi_theme_distance_unit_property_free ( distance->base.left ); + distance->base.left = NULL; + } + if ( distance->base.right ) { + rofi_theme_distance_unit_property_free ( distance->base.right ); + distance->base.right = NULL; + } +} + void rofi_theme_property_free ( Property *p ) { if ( p == NULL ) { @@ -121,6 +182,12 @@ void rofi_theme_property_free ( Property *p ) rofi_theme_property_free ( p->value.link.def_value ); } } + if ( p->type == P_PADDING) { + rofi_theme_distance_property_free( &(p->value.padding.top)); + rofi_theme_distance_property_free( &(p->value.padding.right)); + rofi_theme_distance_property_free( &(p->value.padding.bottom)); + rofi_theme_distance_property_free( &(p->value.padding.left)); + } g_slice_free ( Property, p ); } @@ -149,7 +216,7 @@ static void rofi_theme_insert_listview_backwards_fix ( void ) rofi_theme_widget_add_properties ( tt, table ); - RofiDistance dsize = (RofiDistance){ 1.2, ROFI_PU_CH, ROFI_HL_SOLID }; + RofiDistance dsize = (RofiDistance){ .base = {1.2, ROFI_PU_CH, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, .style = ROFI_HL_SOLID }; Property *pts = rofi_theme_property_create ( P_PADDING ); pts->value.padding.top = pts->value.padding.right = pts->value.padding.bottom = pts->value.padding.left = dsize; pts->name = g_strdup ( "size" ); @@ -162,7 +229,7 @@ static void rofi_theme_insert_listview_backwards_fix ( void ) table = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, (GDestroyNotify) rofi_theme_property_free ); Property *psp = rofi_theme_property_create ( P_PADDING ); psp->name = g_strdup ( "spacing" ); - RofiDistance d = (RofiDistance){ 5, ROFI_PU_PX, ROFI_HL_SOLID }; + RofiDistance d = (RofiDistance){ .base = {5, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, .style = ROFI_HL_SOLID }; psp->value.padding = (RofiPadding){ d, d, d, d }; g_hash_table_replace ( table, psp->name, psp ); rofi_theme_widget_add_properties ( t, table ); @@ -187,6 +254,9 @@ void rofi_theme_free ( ThemeWidget *widget ) g_hash_table_destroy ( widget->properties ); widget->properties = NULL; } + if ( widget->media ) { + g_slice_free ( ThemeMedia, widget->media ); + } for ( unsigned int i = 0; i < widget->num_widgets; i++ ) { rofi_theme_free ( widget->widgets[i] ); } @@ -204,22 +274,58 @@ inline static void printf_double ( double d ) g_ascii_formatd ( buf, G_ASCII_DTOSTR_BUF_SIZE, "%.4lf", d ); fputs ( buf, stdout ); } -static void rofi_theme_print_distance ( RofiDistance d ) + +static void rofi_theme_print_distance_unit ( RofiDistanceUnit *unit ) { - if ( d.type == ROFI_PU_PX ) { - printf ( "%upx ", (unsigned int) d.distance ); - } - else if ( d.type == ROFI_PU_PERCENT ) { - printf_double ( d.distance ); - fputs ( "%% ", stdout ); + if ( unit->modtype == ROFI_DISTANCE_MODIFIER_GROUP ) + fputs("( " , stdout); + if ( unit->left ) + rofi_theme_print_distance_unit ( unit->left ); + + if ( unit->modtype == ROFI_DISTANCE_MODIFIER_ADD ) { + fputs ( " + ", stdout ); + } else if ( unit->modtype == ROFI_DISTANCE_MODIFIER_SUBTRACT ) { + fputs ( " - ", stdout ); + } else if ( unit->modtype == ROFI_DISTANCE_MODIFIER_DIVIDE ) { + fputs ( " / ", stdout ); + } else if ( unit->modtype == ROFI_DISTANCE_MODIFIER_MULTIPLY) { + fputs ( " * ", stdout ); + } else if ( unit->modtype == ROFI_DISTANCE_MODIFIER_MODULO) { + fputs ( " % ", stdout ); + } + if ( unit->right ) + rofi_theme_print_distance_unit ( unit->right ); + + if ( unit->modtype == ROFI_DISTANCE_MODIFIER_NONE ) + { + if ( unit->type == ROFI_PU_PX ) { + printf ( "%upx ", (unsigned int) unit->distance ); + } + else if ( unit->type == ROFI_PU_PERCENT ) { + printf_double ( unit->distance ); + fputs ( "% ", stdout ); + } + else if ( unit->type == ROFI_PU_CH ) { + printf_double ( unit->distance ); + fputs ( "ch ", stdout ); + } + else { + printf_double ( unit->distance ); + fputs ( "em ", stdout ); + } } - else if ( d.type == ROFI_PU_CH ) { - printf_double ( d.distance ); - fputs ( "ch ", stdout ); + if ( unit->modtype == ROFI_DISTANCE_MODIFIER_GROUP ) + fputs(" )" , stdout); +} + +static void rofi_theme_print_distance ( RofiDistance d ) +{ + if ( d.base.modtype == ROFI_DISTANCE_MODIFIER_GROUP ){ + fputs( "calc( ", stdout ); } - else { - printf_double ( d.distance ); - fputs ( "em ", stdout ); + rofi_theme_print_distance_unit ( &(d.base) ); + if ( d.base.modtype == ROFI_DISTANCE_MODIFIER_GROUP ){ + fputs( ")", stdout ); } if ( d.style == ROFI_HL_DASH ) { printf ( "dash " ); @@ -636,17 +742,17 @@ RofiDistance rofi_theme_get_distance ( const widget *widget, const char *propert if ( widget->parent ) { return rofi_theme_get_distance ( widget->parent, property, def ); } - return (RofiDistance){ def, ROFI_PU_PX, ROFI_HL_SOLID }; + return (RofiDistance){ .base = {def, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, .style = ROFI_HL_SOLID }; } if ( p->type == P_INTEGER ) { - return (RofiDistance){ p->value.i, ROFI_PU_PX, ROFI_HL_SOLID }; + return (RofiDistance){ .base = { p->value.i, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, .style = ROFI_HL_SOLID }; } else { return p->value.padding.left; } } g_debug ( "Theme entry: #%s %s property %s unset.", widget->name, widget->state ? widget->state : "", property ); - return (RofiDistance){ def, ROFI_PU_PX, ROFI_HL_SOLID }; + return (RofiDistance){ .base = {def, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, .style = ROFI_HL_SOLID }; } int rofi_theme_get_boolean ( const widget *widget, const char *property, int def ) @@ -762,7 +868,7 @@ RofiPadding rofi_theme_get_padding ( const widget *widget, const char *property, pad = p->value.padding; } else { - RofiDistance d = (RofiDistance){ p->value.i, ROFI_PU_PX, ROFI_HL_SOLID }; + RofiDistance d = (RofiDistance){ .base = {p->value.i, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, .style = ROFI_HL_SOLID }; return (RofiPadding){ d, d, d, d }; } } @@ -813,27 +919,74 @@ RofiHighlightColorStyle rofi_theme_get_highlight ( widget *widget, const char *p return th; } -int distance_get_pixel ( RofiDistance d, RofiOrientation ori ) +static int get_pixels ( RofiDistanceUnit *unit, RofiOrientation ori ) { - if ( d.type == ROFI_PU_EM ) { - return d.distance * textbox_get_estimated_char_height (); + int val = unit->distance; + + + if ( unit->type == ROFI_PU_EM ) { + val = unit->distance * textbox_get_estimated_char_height (); } - else if ( d.type == ROFI_PU_CH ) { - return d.distance * textbox_get_estimated_ch (); + else if ( unit->type == ROFI_PU_CH ) { + val = unit->distance * textbox_get_estimated_ch (); } - else if ( d.type == ROFI_PU_PERCENT ) { + else if ( unit->type == ROFI_PU_PERCENT ) { if ( ori == ROFI_ORIENTATION_VERTICAL ) { int height = 0; rofi_view_get_current_monitor ( NULL, &height ); - return ( d.distance * height ) / ( 100.0 ); + val = ( unit->distance * height ) / ( 100.0 ); } else { int width = 0; rofi_view_get_current_monitor ( &width, NULL ); - return ( d.distance * width ) / ( 100.0 ); + val = ( unit->distance * width ) / ( 100.0 ); } } - return d.distance; + return val; +} + + +static int distance_unit_get_pixel ( RofiDistanceUnit *unit, RofiOrientation ori ) +{ + switch ( unit->modtype) + { + case ROFI_DISTANCE_MODIFIER_GROUP: + return distance_unit_get_pixel ( unit->left, ori ); + break; + case ROFI_DISTANCE_MODIFIER_ADD: + return distance_unit_get_pixel ( unit->left, ori)+ distance_unit_get_pixel ( unit->right, ori); + case ROFI_DISTANCE_MODIFIER_SUBTRACT: + return distance_unit_get_pixel ( unit->left, ori)- distance_unit_get_pixel ( unit->right, ori); + case ROFI_DISTANCE_MODIFIER_MULTIPLY: + return distance_unit_get_pixel ( unit->left, ori)* distance_unit_get_pixel ( unit->right, ori); + case ROFI_DISTANCE_MODIFIER_DIVIDE: + { + int a = distance_unit_get_pixel ( unit->left, ori); + int b = distance_unit_get_pixel ( unit->right, ori); + if ( b != 0 ) { + return a/b; + } + return a; + } + case ROFI_DISTANCE_MODIFIER_MODULO: + { + int a = distance_unit_get_pixel ( unit->left, ori); + int b = distance_unit_get_pixel ( unit->right, ori); + if ( b != 0 ) { + return a%b; + } + return 0; + } + default: + break; + } + return get_pixels ( unit, ori ); +} + + +int distance_get_pixel ( RofiDistance d, RofiOrientation ori ) +{ + return distance_unit_get_pixel ( &(d.base), ori); } void distance_get_linestyle ( RofiDistance d, cairo_t *draw ) diff --git a/source/widgets/scrollbar.c b/source/widgets/scrollbar.c index dd057591..699ab07e 100644 --- a/source/widgets/scrollbar.c +++ b/source/widgets/scrollbar.c @@ -51,7 +51,7 @@ static int scrollbar_get_desired_height ( widget *wid ) // This should behave more like a real scrollbar. guint scrollbar_scroll_get_line ( const scrollbar *sb, int y ) { - y -= sb->widget.border.top.distance; + y -= sb->widget.border.top.base.distance; if ( y < 0 ) { return 0; } diff --git a/source/widgets/widget.c b/source/widgets/widget.c index 5dfd9437..c0e89859 100644 --- a/source/widgets/widget.c +++ b/source/widgets/widget.c @@ -40,11 +40,11 @@ void widget_init ( widget *wid, widget *parent, WidgetType type, const char *nam wid->parent = parent; wid->name = g_strdup ( name ); wid->def_padding = - (RofiPadding){ { WIDGET_DEFAULT_PADDING, ROFI_PU_PX, ROFI_HL_SOLID }, { WIDGET_DEFAULT_PADDING, ROFI_PU_PX, ROFI_HL_SOLID }, { WIDGET_DEFAULT_PADDING, ROFI_PU_PX, ROFI_HL_SOLID }, - { WIDGET_DEFAULT_PADDING, ROFI_PU_PX, ROFI_HL_SOLID } }; - wid->def_border = (RofiPadding){ { 0, ROFI_PU_PX, ROFI_HL_SOLID }, { 0, ROFI_PU_PX, ROFI_HL_SOLID }, { 0, ROFI_PU_PX, ROFI_HL_SOLID }, { 0, ROFI_PU_PX, ROFI_HL_SOLID } }; - wid->def_border_radius = (RofiPadding){ { 0, ROFI_PU_PX, ROFI_HL_SOLID }, { 0, ROFI_PU_PX, ROFI_HL_SOLID }, { 0, ROFI_PU_PX, ROFI_HL_SOLID }, { 0, ROFI_PU_PX, ROFI_HL_SOLID } }; - wid->def_margin = (RofiPadding){ { 0, ROFI_PU_PX, ROFI_HL_SOLID }, { 0, ROFI_PU_PX, ROFI_HL_SOLID }, { 0, ROFI_PU_PX, ROFI_HL_SOLID }, { 0, ROFI_PU_PX, ROFI_HL_SOLID } }; + (RofiPadding){ { {WIDGET_DEFAULT_PADDING, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID }, { {WIDGET_DEFAULT_PADDING, ROFI_PU_PX,ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID }, { {WIDGET_DEFAULT_PADDING, ROFI_PU_PX,ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID }, + { {WIDGET_DEFAULT_PADDING, ROFI_PU_PX,ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID } }; + wid->def_border = (RofiPadding){ { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL} , ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID } }; + wid->def_border_radius = (RofiPadding){ { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL} , ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID } }; + wid->def_margin = (RofiPadding){ { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL} , ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID }, { {0, ROFI_PU_PX, ROFI_DISTANCE_MODIFIER_NONE, NULL, NULL}, ROFI_HL_SOLID } }; wid->padding = rofi_theme_get_padding ( wid, "padding", wid->def_padding ); wid->border = rofi_theme_get_padding ( wid, "border", wid->def_border ); -- cgit v1.2.3