#!/usr/bin/env sh
#      turntab v0.4.2 extremely alpha
#         written by Kermie BREYDON
#          on Boon Wurrung country
#                  in 2020
#           for the public domain
#
# https://www.breydon.id.au/puting/turntab/

printf "Hello, turntab speaking. I get the orientations
of tablet input and display to match each other.\n"

# Functions!

software () {
  printf '
This is turntab v0.4.2 extremely alpha.
<https://www.breydon.id.au/puting/turntab/>
Written October 2020.
Author: Kermie BREYDON (they/them/their).

This software is in the public domain. It is
free for use by anyone and for any purpose. The
software is offered "as is", without warranty of
any kind.

turntab has been written on Boon Wurrung land.
I pay my respects to the Boon Wurrung people,
especially their Elders, and to all Indigineous
communities within whose lands, waters or skies
this software is read, adapted or run.

                       \342\237\244\342\237\245
'
}

help () {
  printf "
  help       Shows this usage list.
  version    Shows the current software version.

  input      Makes the tablet input and the
             teletype-style consoles that use a
             frame-buffer (FBTTYs) match the
             graphical display's orientation.

  output     Orients the graphical display and
             FBTTYs to match the tablet input.

  increment  Corrects tablet input and FBTTYs to
             match the graphical display, then
             turns them all 90 degrees clockwise.

  [o]        Sets all frame-buffer consoles,
             graphical display and tablet input
             to the [o] orientation.

  x          Affects only the graphical display
             and tablet input.

  Options for [o] include 0, 1, 2, or 3
  but also terms such as left or ccw.
  For instance:  turntab x right\n"
}

translate () {
case "$goal" in
  *normal|*none|*0)
    xoutputori="normal";
    xinputori="none";
    fbcori="0";
    orientation="upright (not rotated)";;
  *left|*ccw|*3)
    xoutputori="left";
    xinputori="ccw";
    fbcori="3";
    orientation="turned on its left";;
  *inverted|*half|*2)
    xoutputori="inverted";
    xinputori="half";
    fbcori="2";
    orientation="upside-down to usual";;
  *right|*cw|*1)
    xoutputori="right";
    xinputori="cw";
    fbcori="1";
    orientation="turned on its right";;
esac
}

incrementgoals () {
case "$goal" in
  normal|none|0)
    xoutputori="right";
    xinputori="cw";
    fbcori="1";
    orientation="turned on its right";;
  right|cw|1)
    xoutputori="inverted";
    xinputori="half";
    fbcori="2";
    orientation="upside-down to usual";;
  inverted|half|2)
    xoutputori="left";
    xinputori="ccw";
    fbcori="3";
    orientation="turned on its left";;
  left|ccw|3)
    xoutputori="normal";
    xinputori="none";
    fbcori="0";
    orientation="upright (not rotated)";;
esac
printf "\nLet's make it $orientation.\n"
}

sussxoutputori () {
  printf "\nSussing out display (via xrandr)...\n"
  xoutputori="$(xrandr --verbose | awk -e 'BEGIN {RS ="\\(normal left inverted"} $0 ~ "Screen" {print $NF}')"
  if test "$xoutputori" = "normal" -o "$xoutputori" = "left" -o "$xoutputori" = "inverted" -o "$xoutputori" = "right"; then
    goal="$xoutputori"
    translate
    printf "OK. I reckon the display is $orientation.\n"
  else
    printf "
Sorry, but this time I could not tell which way
the graphical display has been turned.
(Assuming that there even is one?)

Please note that I depend on the X Window System
for graphical matters and am not very clever.\n"
    exit
  fi
}

findtab () {
printf "\nIdentifying forms of tablet input (via xsetwacom)...\n"
devices="$( xsetwacom list | sed -E 's/.*id: //; s/\t.*//')"
}

sussxinputori () {
findtab
printf "\nSussing out tablet orientation (via xsetwacom)...\n"
for device in $devices; do
  xinputori="$(xsetwacom get $device rotate)"
  break
done
if test "$xinputori" = "none" -o "$xinputori" = "ccw" -o "$xinputori" = "half" -o "$xinputori" = "cw"; then
  goal="$xinputori"
  translate
  printf "OK. I reckon the tablet input is $orientation.\n"
else
  printf "
Sorry, but this time I could not tell which way
any tablet input is oriented.

Please note that the only tablets I handle are
Wacom hardware in use by the X Window System.\n"
  exit
fi
}

orientxoutput () {
printf "
Trying to orient graphical display (via xrandr)...\n"
xrandr -o $xoutputori
if test "$(xrandr --verbose | awk -e 'BEGIN {RS ="\\(normal left inverted"} $0 ~ "Screen" {print $NF}')" = "$xoutputori"; then
  printf "Seems OK, from my perspective.\n"
else
  printf "Sorry, I could not correct the graphical display.\n"
fi
}

orientxinput () {
findtab
if test "$devices" = ""; then
  printf "Sorry, I can't find any.

Please note that I can only do so within the
X Window System and for certain Wacom devices.\n"
else
  for device in $devices; do
    if test "$device" -gt 0 -a "$device" -lt 100; then
      printf "Trying to correct tablet orientation (via xsetwacom)...\n"
      for device in $devices; do
        xsetwacom set $device rotate $xinputori
      done
      printf "Done. Hopefully.\n"
    else
      printf "Sorry, this time, I cannot make sense of
the system's response.\n"
    fi
    break
  done
fi
}

orientfbc () {
printf "
About to orient the text consoles that use a
frame-buffer. This requires special permission,
so you might be asked for a password...\n"
fbcresult="$(echo $fbcori | sudo tee /sys/class/graphics/fbcon/rotate_all)"
if test "$fbcresult" = "$fbcori"; then
  printf "OK. I think that worked.\n"
else
  printf "\nSorry, I could not correct them.\n"
fi
}

# Making sense of commands!

case "$1" in
  ""|*help|h|-h)
    printf "\nThings you can write after $0:\n"
    help
    ;;
  *version|v|-v)
    software
    ;;
  *increment|*cycle|c|-c)
    sussxoutputori
    incrementgoals
    orientxoutput
    orientxinput
    orientfbc
    ;;
  *input|i|-i)
    sussxoutputori
    orientxinput
    orientfbc
    ;;
  *output|o|-o)
    sussxinputori
    orientxoutput
    orientfbc
    ;;
  *0|*1|*2|*3|*normal|*right|*inverted|*left|*none|*cw|*half|*ccw)
    goal="$1"
    translate
    orientxoutput
    orientxinput
    orientfbc
    ;;
  *x)
    case "$2" in
      *increment|*cycle|c|-c)
        sussxoutputori
        incrementgoals
        orientxoutput
        orientxinput
        ;;
      ""|*input|i|-i)
        sussxoutputori
        orientxinput
        ;;
      *output|o|-o)
        sussxinputori
        orientxoutput
        ;;
      *0|*1|*2|*3|*normal|*right|*inverted|*left|*none|*cw|*half|*ccw)
        goal="$2"
        translate
        orientxoutput
        orientxinput
        ;;
      *)
        printf "Sorry, do what?"
        ;;
    esac
    ;;
  *)
    printf "
Sorry, I do not know what you mean by $1.
Here are some other things we could try next:\n"
    help
    ;;
esac

# Humphrey, we're leaving!

exit $?
