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 # 2012 Jan Larres <jan@majutsushi.net>
9 # Permission is hereby granted, free of charge, to any person obtaining a copy
10 # of this software and associated documentation files (the "Software"), to
11 # deal in the Software without restriction, including without limitation the
12 # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
13 # sell copies of the Software, and to permit persons to whom the Software is
14 # furnished to do so, subject to the following conditions:
16 # The above copyright notice and this permission notice shall be included in
17 # all copies or substantial portions of the Software.
19 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
27 # URL: https://github.com/majutsushi/urxvt-font-size
30 # https://github.com/dave0/urxvt-font-size
31 # https://github.com/noah/urxvt-font
36 # Add font-size to the list of perl extensions:
37 # URxvt.perl-ext-common: ...,font-size
39 # Add some keybindings:
40 # URxvt.keysym.C-Up: perl:font-size:increase
41 # URxvt.keysym.C-Down: perl:font-size:decrease
42 # URxvt.keysym.C-S-Up: perl:font-size:incglobal
43 # URxvt.keysym.C-S-Down: perl:font-size:decglobal
45 # Supported functions:
46 # - increase/decrease:
47 # increase or decrease the font size of the current terminal.
48 # - incglobal/decglobal:
49 # same as above and also adjust the X server values so all newly started
50 # terminals will use the same fontsize.
52 # same as incglobal/decglobal and also modify the ~/.Xresources file so
53 # the changed font sizes will persist over a restart of the X server or
63 "boldItalicFont" => 713
68 my ($self, $cmd) = @_;
70 if ($cmd eq "font-size:increase") {
71 fonts_change_size
($self, 1, 0);
72 } elsif ($cmd eq "font-size:decrease") {
73 fonts_change_size
($self, -1, 0);
74 } elsif ($cmd eq "font-size:incglobal") {
75 fonts_change_size
($self, 1, 1);
76 } elsif ($cmd eq "font-size:decglobal") {
77 fonts_change_size
($self, -1, 1);
78 } elsif ($cmd eq "font-size:incsave") {
79 fonts_change_size
($self, 1, 2);
80 } elsif ($cmd eq "font-size:decsave") {
81 fonts_change_size
($self, -1, 2);
87 my ($term, $change, $save) = @_;
91 my $curres = $term->resource('font');
95 my @curfonts = split(/,/, $curres);
97 my $basefont = shift(@curfonts);
98 my ($newbasefont, $newbasesize) = handle_font
($term, $basefont, $change, 0);
99 push @newfonts, $newbasefont;
101 # Only adjust other fonts if base font changed
102 if ($newbasefont ne $basefont) {
103 foreach my $font (@curfonts) {
104 my ($newfont, $newsize) = handle_font
($term, $font, $change, $newbasesize);
105 push @newfonts, $newfont;
107 my $newres = join(",", @newfonts);
108 font_apply_new
($term, $newres, "font", $save);
110 handle_type
($term, "boldFont", $change, $newbasesize, $save);
111 handle_type
($term, "italicFont", $change, $newbasesize, $save);
112 handle_type
($term, "boldItalicFont", $change, $newbasesize, $save);
116 # write the new values back to the file
117 my $xresources = readlink $ENV{"HOME"} . "/.Xresources";
118 system("xrdb -edit " . $xresources);
124 my ($term, $type, $change, $basesize, $save) = @_;
126 my $curres = $term->resource($type);
130 my @curfonts = split(/,/, $curres);
133 foreach my $font (@curfonts) {
134 my ($newfont, $newsize) = handle_font
($term, $font, $change, $basesize);
135 push @newfonts, $newfont;
138 my $newres = join(",", @newfonts);
139 font_apply_new
($term, $newres, $type, $save);
144 my ($term, $font, $change, $basesize) = @_;
150 if ($font =~ /^\s*x:/) {
154 if ($font =~ /^\s*(\[.*\])?xft:/) {
155 ($newfont, $newsize) = font_change_size_xft
($term, $font, $change, $basesize);
156 } elsif ($font =~ /^\s*-/) {
157 ($newfont, $newsize) = font_change_size_x11
($term, $font, $change, $basesize);
159 # check whether the font is a valid alias and if yes resolve it to the
161 my $lsfinfo = `xlsfonts -l $font 2>/dev/null`;
163 if ($lsfinfo eq "") {
164 # not a valid alias, ring the bell if it is the base font and just
165 # return the current font
166 if ($basesize == 0) {
169 return ($font, $basesize);
172 my $fontinfo = (split(/\n/, $lsfinfo))[-1];
173 my ($fontfull) = ($fontinfo =~ /\s+([-a-z0-9]+$)/);
174 ($newfont, $newsize) = font_change_size_x11
($term, $fontfull, $change, $basesize);
177 # $term->scr_add_lines("\r\nNew font is $newfont\n");
179 $newfont = "x:$newfont";
181 return ($newfont, $newsize);
184 sub font_change_size_xft
186 my ($term, $fontstring, $change, $basesize) = @_;
188 my @pieces = split(/:/, $fontstring);
193 foreach my $piece (@pieces) {
194 if ($piece =~ /pixelsize=(\d+)/) {
197 if ($basesize != 0) {
198 $new_size = $basesize;
200 $new_size = ($change > 0 ?
($size + 1) : ($size - 1));
203 $piece =~ s/pixelsize=$size/pixelsize=$new_size/;
205 push @resized, $piece;
208 my $resized_str = join(":", @resized);
210 # don't make fonts too small
211 if ($new_size >= 10) {
212 return ($resized_str, $new_size);
214 if ($basesize == 0) {
217 return ($fontstring, $size);
221 sub font_change_size_x11
223 my ($term, $fontstring, $change, $basesize) = @_;
225 #-xos4-terminus-medium-r-normal-*-12-*-*-*-*-*-*-1
227 my @fields = qw(foundry family weight slant setwidth style pixelSize pointSize Xresolution Yresolution spacing averageWidth registry encoding);
230 $fontstring =~ s/^-//; # Strip leading - before split
231 @font{@fields} = split(/-/, $fontstring);
233 if ($font{registry
} eq '*') {
234 $font{registry
} ='iso8859';
237 # Blank out the size for the pattern
239 $pattern{foundry
} = '*';
240 $pattern{setwidth
} = '*';
241 $pattern{pixelSize
} = '*';
242 $pattern{pointSize
} = '*';
243 # if ($basesize != 0) {
244 # $pattern{Xresolution} = '*';
245 # $pattern{Yresolution} = '*';
247 $pattern{averageWidth
} = '*';
248 # make sure there are no empty fields
249 foreach my $field (@fields) {
250 $pattern{$field} = '*' unless defined($pattern{$field});
252 my $new_fontstring = '-' . join('-', @pattern{@fields});
255 # $term->scr_add_lines("\r\nPattern is $new_fontstring\n");
256 open(FOO
, "xlsfonts -fn '$new_fontstring' | sort -u |") or die $!;
259 s/^-//; # Strip leading '-' before split
260 my @fontdata = split(/-/, $_);
262 push @possible, [$fontdata[6], "-$_"];
263 # $term->scr_add_lines("\r\npossibly $fontdata[6] $_\n");
268 die "No possible fonts!";
271 if ($basesize != 0) {
272 # sort by font size, descending
273 @possible = sort {$b->[0] <=> $a->[0]} @possible;
275 # font is not the base font, so find the largest font that is at most
276 # as large as the base font. If the largest possible font is smaller
277 # than the base font bail and hope that a 0-size font can be found at
278 # the end of the function
279 if ($possible[0]->[0] > $basesize) {
280 foreach my $candidate (@possible) {
281 if ($candidate->[0] <= $basesize) {
282 return ($candidate->[1], $candidate->[0]);
286 } elsif ($change > 0) {
287 # sort by font size, ascending
288 @possible = sort {$a->[0] <=> $b->[0]} @possible;
290 foreach my $candidate (@possible) {
291 if ($candidate->[0] > $font{pixelSize
}) {
292 return ($candidate->[1], $candidate->[0]);
295 } elsif ($change < 0) {
296 # sort by font size, descending
297 @possible = sort {$b->[0] <=> $a->[0]} @possible;
299 foreach my $candidate (@possible) {
300 if ($candidate->[0] < $font{pixelSize
} && $candidate->[0] != 0) {
301 return ($candidate->[1], $candidate->[0]);
306 # no fitting font available, check whether a 0-size font can be used to
307 # fit the size of the base font
308 @possible = sort {$a->[0] <=> $b->[0]} @possible;
309 if ($basesize != 0 && $possible[0]->[0] == 0) {
310 return ($possible[0]->[1], $basesize);
312 # if there is absolutely no smaller/larger font that can be used
313 # return the current one, and beep if this is the base font
314 if ($basesize == 0) {
317 return ("-$fontstring", $font{pixelSize
});
323 my ($term, $newfont, $type, $save) = @_;
325 # $term->scr_add_lines("\r\nnew font is $newfont\n");
327 $term->cmd_parse("\033]" . $escapecodes{$type} . ";" . $newfont . "\033\\");
330 # system("xrdb -load " . X_RESOURCES);
333 # merge the new values
334 open(XRDB_MERGE
, "| xrdb -merge") || die "can't fork: $!";
335 local $SIG{PIPE
} = sub { die "xrdb pipe broken" };
336 print XRDB_MERGE
"URxvt." . $type . ": " . $newfont;
337 close(XRDB_MERGE
) || die "bad xrdb: $! $?";