#!/usr/bin/env bash
# x-resize-display --- resize current display or show available resolutions
# Author: Noah Friedman <friedman@splode.com>
# Created: 2019-02-16
# Public domain

# $Id: x-resize-display,v 1.5 2019/06/18 05:53:07 friedman Exp $

xrandr1() { xrandr --screen ${DISPLAY##*.} "$@"; }

get_pri()
{
    xrandr1 | sed -ne '/^\([^ ]*\) .* primary .*/{s//\1/p;q;}' -e '$q 1'
}

get_out()
{
    if ! get_pri; then
        xrandr1 | sed -ne '/^\([^ ]*\)  *connected\( primary\)* [0-9]*x[0-9].*/{s//\1/p;q;}' \
                       -e '$q 1'
    fi
}

get_res()
{
    output=${1-$(get_out)}
    xrandr1 | sed -n \
                  -e "/^$output  */{" \
                  -e '  :l' \
                  -e '  n' \
                  -e '  /^  *\([0-9x]*\)\([@_][0-9@_.]*\)*  *[^*+]*\([*+]*\).*/!d' \
                  -e '  s//\1 \3/p' \
                  -e '  b l' \
                  -e '}'
}

set_res()
{
    res=$1                 ; shift
    output=${1-$(get_out)} ; shift

    xrandr1 --output "$output" --mode "$res" "$@";
}

gcd()
{
    test $2 -gt $1 && set -- $2 $1
    while (( $1 % $2 != 0 )); do
        set -- $(( $1 - $2 )) $2
        test $2 -gt $1 && set -- $2 $1
    done
    gcd=$2
}

aspect()
{
    set -- ${1%%x*} ${1##*x} "$2"
    gcd $1 $2
    let aspect_w=$(( $1 / gcd ))
    let aspect_h=$(( $2 / gcd ))
    echo $1 $2  $aspect_w $aspect_h "$3"
}

sortfn()
{
    case $SORT_BY in
        aspect ) sort -k3,3n  -k4,4n  -k1,1nr -k2,2nr "$@" ;;
        *      ) sort -k1,1nr -k2,2nr -k3,3n  -k4,4n  "$@" ;;
    esac
}

show_avail()
{
    let w=0 h=0 aw=0 ah=0 law=0 lah=0
    local xtra fmt echo=:

    case $SORT_BY in aspect ) echo=echo ;; esac

    get_res "$@" |
        while read geom xtra; do
            aspect $geom ${xtra:+"$xtra"}
        done |
        sortfn |
        while read w h aw ah xtra; do
            [  $aw -ne $law ] ||
            [  $ah -ne $lah ] &&
            [ $law -ne 0 ]    && $echo

            law=$aw lah=$ah
            rat=$(dc -e "2 k $aw $ah / p")
            fmt="%4sx%-4s  %3s:%-2s %s"
            case ${xtra:+isset} in isset ) fmt="$fmt  %s" ;; esac

            printf "$fmt\n" $w $h $aw $ah $rat ${xtra:+"$xtra"}
        done
    return 1
}

main()
{
    case $DISPLAY in
        *:*.* ) : ;;
        * ) DISPLAY=$DISPLAY.0 ;;
    esac

    case $#:$1 in
        0:* ) : ;;
        *:aspect| *:-aspect | *:--aspect ) shift; SORT_BY=aspect ;;
        *:[0-9]* ) : ;;
        *:* ) output=$1 ; shift $# ;;
    esac

    case $# in
        0 ) show_avail $output ;;
        * ) set_res "$@" ;;
    esac
}

main "$@"

# eof
