All patches and comments are welcome. Please squash your changes to logical
commits before using git-format-patch and git-send-email to
patches@git.madduck.net.
If you'd read over the Git project's submission guidelines and adhered to them,
I'd be especially grateful.
3 # On-the-fly adjusting of the font size in urxvt
5 # Copyright (c) 2008 David O'Neill
6 # 2012 Noah K. Tilton <noahktilton@gmail.com>
7 # 2009-2012 Simon Lundström <simmel@soy.se>
8 # 2012-2016 Jan Larres <jan@majutsushi.net>
10 # Permission is hereby granted, free of charge, to any person obtaining a copy
11 # of this software and associated documentation files (the "Software"), to
12 # deal in the Software without restriction, including without limitation the
13 # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14 # sell copies of the Software, and to permit persons to whom the Software is
15 # furnished to do so, subject to the following conditions:
17 # The above copyright notice and this permission notice shall be included in
18 # all copies or substantial portions of the Software.
20 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
28 # URL: https://github.com/majutsushi/urxvt-font-size
31 # https://github.com/dave0/urxvt-font-size
32 # https://github.com/noah/urxvt-font
33 # https://github.com/simmel/urxvt-resize-font
36 #:META:X_RESOURCE:%.step:interger:font size increase/decrease step
40 font-size - interactive font size setter
44 Put the font-size script into $HOME/.urxvt/ext/ and add it to the list
45 of enabled perl-extensions in ~/.Xresources:
47 URxvt.perl-ext-common: ...,font-size
51 URxvt.keysym.C-Up: font-size:increase
52 URxvt.keysym.C-Down: font-size:decrease
53 URxvt.keysym.C-S-Up: font-size:incglobal
54 URxvt.keysym.C-S-Down: font-size:decglobal
55 URxvt.keysym.C-equal: font-size:reset
56 URxvt.keysym.C-slash: font-size:show
58 Note that for urxvt versions older than 9.21 the resources have to look like this:
60 URxvt.keysym.C-Up: perl:font-size:increase
61 URxvt.keysym.C-Down: perl:font-size:decrease
62 URxvt.keysym.C-S-Up: perl:font-size:incglobal
63 URxvt.keysym.C-S-Down: perl:font-size:decglobal
64 URxvt.keysym.C-equal perl:font-size:reset
65 URxvt.keysym.C-slash perl:font-size:show
71 =item * increase/decrease:
73 increase or decrease the font size of the current terminal.
75 =item * incglobal/decglobal:
77 same as above and also adjust the X server values so all newly
78 started terminals will use the same fontsize.
80 =item * incsave/decsave:
82 same as incglobal/decglobal and also modify the ~/.Xresources
83 file so the changed font sizes will persist over a restart of
84 the X server or a reboot.
88 reset the font size to the value of the resource when starting
93 show the current value of the 'font' resource in a popup.
97 You can also change the step size that the script will use to increase
100 URxvt.font-size.step: 4
102 The default step size is 1. This means that with this setting a
103 size change sequence would be for example 8->12->16->20 instead of
104 8->9->10->11->12 etc. Please note that many X11 fonts are only
105 available in specific sizes, though, and odd sizes are often not
106 available, resulting in an effective step size of 2 instead of 1
117 "boldItalicFont" => 713
124 $self->{step} = $self->x_resource("%.step") || 1;
126 foreach my $type (qw(font boldFont italicFont boldItalicFont)) {
127 $self->{$type} = $self->x_resource($type) || "undef";
131 # Needed for backwards compatibility with < 9.21
134 my ($self, $cmd) = @_;
136 my $step = $self->{step};
138 if ($cmd eq "font-size:increase") {
139 fonts_change_size($self, $step, 0);
140 } elsif ($cmd eq "font-size:decrease") {
141 fonts_change_size($self, -$step, 0);
142 } elsif ($cmd eq "font-size:incglobal") {
143 fonts_change_size($self, $step, 1);
144 } elsif ($cmd eq "font-size:decglobal") {
145 fonts_change_size($self, -$step, 1);
146 } elsif ($cmd eq "font-size:incsave") {
147 fonts_change_size($self, $step, 2);
148 } elsif ($cmd eq "font-size:decsave") {
149 fonts_change_size($self, -$step, 2);
150 } elsif ($cmd eq "font-size:reset") {
152 } elsif ($cmd eq "font-size:show") {
159 my ($self, $action) = @_;
161 my $step = $self->{step};
163 if ($action eq "increase") {
164 fonts_change_size($self, $step, 0);
165 } elsif ($action eq "decrease") {
166 fonts_change_size($self, -$step, 0);
167 } elsif ($action eq "incglobal") {
168 fonts_change_size($self, $step, 1);
169 } elsif ($action eq "decglobal") {
170 fonts_change_size($self, -$step, 1);
171 } elsif ($action eq "incsave") {
172 fonts_change_size($self, $step, 2);
173 } elsif ($action eq "decsave") {
174 fonts_change_size($self, -$step, 2);
175 } elsif ($action eq "reset") {
177 } elsif ($action eq "show") {
182 sub fonts_change_size
184 my ($term, $delta, $save) = @_;
188 my $curres = $term->resource('font');
190 $term->scr_add_lines("\r\nWarning: No font configured, trying a default.\r\nPlease set a font with the 'URxvt.font' resource.");
193 my @curfonts = split(/\s*,\s*/, $curres);
195 my $basefont = shift(@curfonts);
196 my ($newbasefont, $newbasedelta, $newbasesize) = handle_font($term, $basefont, $delta, 0, 0);
197 push @newfonts, $newbasefont;
199 # Only adjust other fonts if base font changed
200 if ($newbasefont ne $basefont) {
201 foreach my $font (@curfonts) {
202 my ($newfont, $newdelta, $newsize) = handle_font($term, $font, $delta, $newbasedelta, $newbasesize);
203 push @newfonts, $newfont;
205 my $newres = join(",", @newfonts);
206 font_apply_new($term, $newres, "font", $save);
208 handle_type($term, "boldFont", $delta, $newbasedelta, $newbasesize, $save);
209 handle_type($term, "italicFont", $delta, $newbasedelta, $newbasesize, $save);
210 handle_type($term, "boldItalicFont", $delta, $newbasedelta, $newbasesize, $save);
214 # write the new values back to the file
215 my $xresources = readlink $ENV{"HOME"} . "/.Xresources";
216 system("xrdb -edit " . $xresources);
224 foreach my $type (qw(font boldFont italicFont boldItalicFont)) {
225 my $initial = $term->{$type};
226 if ($initial ne "undef") {
227 font_apply_new($term, $initial, $type, 0);
236 my $out = $term->resource('font');
237 $out =~ s/\s*,\s*/\n/g;
239 $term->{'font-size'}{'overlay'} = {
240 overlay => $term->overlay_simple(0, -1, $out),
241 timer => urxvt::timer->new->start(urxvt::NOW + 5)->cb(
243 delete $term->{'font-size'}{'overlay'};
251 my ($term, $type, $delta, $basedelta, $basesize, $save) = @_;
253 my $curres = $term->resource($type);
257 my @curfonts = split(/\s*,\s*/, $curres);
260 foreach my $font (@curfonts) {
261 my ($newfont, $newdelta, $newsize) = handle_font($term, $font, $delta, $basedelta, $basesize);
262 push @newfonts, $newfont;
265 my $newres = join(",", @newfonts);
266 font_apply_new($term, $newres, $type, $save);
271 my ($term, $font, $delta, $basedelta, $basesize) = @_;
278 if ($font =~ /^\s*x:/) {
282 if ($font =~ /^\s*(\[.*\])?xft:/) {
283 ($newfont, $newdelta, $newsize) = font_change_size_xft($term, $font, $delta, $basedelta, $basesize);
284 } elsif ($font =~ /^\s*-/) {
285 ($newfont, $newdelta, $newsize) = font_change_size_xlfd($term, $font, $delta, $basedelta, $basesize);
287 # check whether the font is a valid alias and if yes resolve it to the
289 my $lsfinfo = `xlsfonts -l $font 2>/dev/null`;
291 if ($lsfinfo eq "") {
292 # not a valid alias, ring the bell if it is the base font and just
293 # return the current font
294 if ($basesize == 0) {
297 return ($font, $basedelta, $basesize);
300 my $fontinfo = (split(/\n/, $lsfinfo))[-1];
301 my ($fontfull) = ($fontinfo =~ /\s+([-a-z0-9]+$)/);
302 ($newfont, $newdelta, $newsize) = font_change_size_xlfd($term, $fontfull, $delta, $basedelta, $basesize);
305 # $term->scr_add_lines("\r\nNew font is $newfont\n");
307 $newfont = "x:$newfont";
309 return ($newfont, $newdelta, $newsize);
312 sub font_change_size_xft
314 my ($term, $fontstring, $delta, $basedelta, $basesize) = @_;
316 my @pieces = split(/:/, $fontstring);
321 foreach my $piece (@pieces) {
322 if ($piece =~ /^(?:(?:pixel)?size=|[^=-]+-)(\d+(\.\d*)?)$/) {
325 if ($basedelta != 0) {
326 $new_size = $size + $basedelta;
328 $new_size = $size + $delta;
331 $piece =~ s/(=|-)$size/$1$new_size/;
333 push @resized, $piece;
336 my $resized_str = join(":", @resized);
338 # don't make fonts too small
339 if ($new_size >= 6) {
340 return ($resized_str, $new_size - $size, $new_size);
342 if ($basesize == 0) {
345 return ($fontstring, 0, $size);
349 sub font_change_size_xlfd
351 my ($term, $fontstring, $delta, $basedelta, $basesize) = @_;
353 #-xos4-terminus-medium-r-normal-*-12-*-*-*-*-*-*-1
355 my @fields = qw(foundry family weight slant setwidth style pixelSize pointSize Xresolution Yresolution spacing averageWidth registry encoding);
358 $fontstring =~ s/^-//; # Strip leading - before split
359 @font{@fields} = split(/-/, $fontstring);
361 if ($font{pixelSize} eq '*') {
362 $term->scr_add_lines("\r\nWarning: Font size undefined, assuming 12.\r\nPlease set the 'URxvt.font' resource to a font with a concrete size.");
363 $font{pixelSize} = '12'
365 if ($font{registry} eq '*') {
366 $font{registry} ='iso8859';
369 # Blank out the size for the pattern
371 $pattern{foundry} = '*';
372 $pattern{setwidth} = '*';
373 $pattern{pixelSize} = '*';
374 $pattern{pointSize} = '*';
375 # if ($basesize != 0) {
376 # $pattern{Xresolution} = '*';
377 # $pattern{Yresolution} = '*';
379 $pattern{averageWidth} = '*';
380 # make sure there are no empty fields
381 foreach my $field (@fields) {
382 $pattern{$field} = '*' unless defined($pattern{$field});
384 my $new_fontstring = '-' . join('-', @pattern{@fields});
387 # $term->scr_add_lines("\r\nPattern is $new_fontstring\n");
388 open(FOO, "xlsfonts -fn '$new_fontstring' | sort -u |") or die $!;
391 s/^-//; # Strip leading '-' before split
392 my @fontdata = split(/-/, $_);
394 push @candidates, [$fontdata[6], "-$_"];
395 # $term->scr_add_lines("\r\npossibly $fontdata[6] $_\n");
400 die "No possible fonts!";
403 if ($basesize != 0) {
404 # sort by font size, descending
405 @candidates = sort {$b->[0] <=> $a->[0]} @candidates;
407 # font is not the base font, so find the largest font that is at most
408 # as large as the base font. If the largest possible font is smaller
409 # than the base font bail and hope that a 0-size font can be found at
410 # the end of the function
411 if ($candidates[0]->[0] > $basesize) {
412 foreach my $candidate (@candidates) {
413 if ($candidate->[0] <= $basesize) {
414 return ($candidate->[1], $candidate->[0] - $font{pixelSize}, $candidate->[0]);
418 } elsif ($delta > 0) {
419 # sort by font size, ascending
420 @candidates = sort {$a->[0] <=> $b->[0]} @candidates;
422 foreach my $candidate (@candidates) {
423 if ($candidate->[0] >= $font{pixelSize} + $delta) {
424 return ($candidate->[1], $candidate->[0] - $font{pixelSize}, $candidate->[0]);
427 } elsif ($delta < 0) {
428 # sort by font size, descending
429 @candidates = sort {$b->[0] <=> $a->[0]} @candidates;
431 foreach my $candidate (@candidates) {
432 if ($candidate->[0] <= $font{pixelSize} + $delta && $candidate->[0] != 0) {
433 return ($candidate->[1], $candidate->[0] - $font{pixelSize}, $candidate->[0]);
438 # no fitting font available, check whether a 0-size font can be used to
439 # fit the size of the base font
440 @candidates = sort {$a->[0] <=> $b->[0]} @candidates;
441 if ($basesize != 0 && $candidates[0]->[0] == 0) {
442 return ($candidates[0]->[1], $basedelta, $basesize);
444 # if there is absolutely no smaller/larger font that can be used
445 # return the current one, and beep if this is the base font
446 if ($basesize == 0) {
449 return ("-$fontstring", 0, $font{pixelSize});
455 my ($term, $newfont, $type, $save) = @_;
457 # $term->scr_add_lines("\r\nnew font is $newfont\n");
459 $term->cmd_parse("\033]" . $escapecodes{$type} . ";" . $newfont . "\033\\");
462 # system("xrdb -load " . X_RESOURCES);
465 # merge the new values
466 open(XRDB_MERGE, "| xrdb -merge") || die "can't fork: $!";
467 local $SIG{PIPE} = sub { die "xrdb pipe broken" };
468 print XRDB_MERGE "URxvt." . $type . ": " . $newfont;
469 close(XRDB_MERGE) || die "bad xrdb: $! $?";