#!/bin/bash
#-------------------------------------------------------------------------------
# translate.sh                              (C) 2005-2022 T.Birnthaler OSTC GmbH
# $Id: translate.sh,v 1.38 2019/11/15 23:06:24 tsbirn Exp $
# Englischen/deutsche Begriff TOPIC uebersetzen per Abfrage der Remote-
# Woerterbuecher LEO.ORG und DICT.CC und/oder dem lokalen Woerterbuch.
# Lokales Woerterbuch interaktiv mit LEO/DICT-Ergebnis ergaenzen falls neues W.
#-------------------------------------------------------------------------------
# Ggfs. vorher HTTP-Proxy definieren per: export HTTP_PROXY="IP:PORT"
#-------------------------------------------------------------------------------
# Faelle:
#
#    |Lokal |Remote| Aktion(en)
# ---+------+------+------------------------------------------------------------
# a) | nein | nein | Zl. "TOPIC... ???" nicht gefunden!" anhaengen
#    |      |      |                    + Sprung zu TOPIC (Zl.ende)
# b) | nein |  ja  | Zl. "TOPIC...    " + ABFRAGE-Ergebnis anhaengen
#    |      |      |                    + Sprung zu TOPIC (Zl.ende)
# c) |  ja  | nein | Alle Zeilen mit TOPIC nach unten verschieben + a)
# d) |  ja  |  ja  | Alle Zeilen mit TOPIC nach unten verschieben + b)
# ---+------+------+------------------------------------------------------------
#
# TODO
# * --no-netrc funktioniert nicht, trotzdem Zugriff auf "~/.netrc"
# * "necessary" wird nicht gefunden?
# * Ideen uebernehmen:
#     function leo
#     {
#         SEARCH="$@"
#         lynx -source "http://dict.leo.org/ende?lg=ende&search=$SEARCH" |
#         grep "TABLE.*/TABLE"  |
#         sed "s/^.*\(<TABLE.*TABLE>\).*$/<HTML><BODY>\1<\/BODY><\/HTML>/"  |
#         lynx -stdin -dump -width=$COLUMNS -nolist
#     }
# * Editor auswaehlbar machen (Option)
# * Proxy, User und Passwort uebergeben:
#     --no-proxy
#     --proxy-user=USER
#     --proxy-pass=PASS
#     --user=USER  --http-user=USER  --ftp-user=USER
#     --pass=PASS  --http-pass=PASS  --ftp-pass=PASS
# * Umgebungsvariablen:
#     HTTP_PROXY   http_proxy
#     HTTPS_PROXY  https_proxy
#     FTP_PROXY    ftp_proxy
#
# DONE
# * Andere Sprachen abfragbar machen:
#   + http://dict.leo.org/chde?lp=chde&search=ruhig
#   + http://dict.leo.org/ende?lp=ende&search=ruhig
#   + http://dict.leo.org/esde?lp=esde&search=ruhig
#   + http://dict.leo.org/frde?lp=frde&search=ruhig
#   + http://dict.leo.org/rude?lp=rude&search=ruhig
# * "sed" durch "perl" ersetzen
# * Zeichensatz UTF-8 -> sed-Aufruf mit Umlauten funktioniert nicht -> perl
# * Lexikon "http://www.dict.cc" hinzufuegen
# * Angehaengten Text per Vi-Kommando erzeugen (damit auch per u=Undo entfernbar)
# * Pruefen ob wget, w3m, iconv, sed, ... installiert
#-------------------------------------------------------------------------------
# Debugging an/aus (auch per Option "-d")
DEBUG="1"
DEBUG=""

# Ausgabesprache + lokales Woerterbuch
LANGUAGE="en"
LOCALDICT="$HOME/.translate.$LANGUAGE"

# Editor
EDITOR="kwrite"
EDITOR="gedit"
EDITOR="vim"

# Hosts fuer Uebersetzung
 LEOFQDN="dict.leo.org"
DICTFQDN="www.dict.cc"
LINGFQDN="www.linguee.de"   # TODO
BABLFQDN="de.bab.la"        # TODO

# Standardeinstellung "welches Woerterbuch verwenden" (letzte Zeile zaehlt)
TYPE="local"  # -l NUR lokales Woerterbuch verwenden
TYPE="remote" # -x NUR Remote-Woerterbucher verwenden
TYPE="both"   # -b BEIDE Woerterbuecher verwenden (1=R,2=L)
TYPE="edit"   # -e Lokales Woerterbuch editieren
TYPE="add"    # -a BEIDE WB verwenden (1=L,2=R) + NUR NEUES TOPIC zu lokalem WB dazu
TYPE="force"  # -f BEIDE WB verwenden (1=L,2=R) + IMMER TOPIC zu lokalem WB dazu

# Breite der linken Vokabelspalte im lokalen Woerterbuch
LEFTCOLWIDTH=39

# VIM-Kommandos
VIMADD=""   # Am Ende des lokalen Woerterbuchs hinzuzufuegender Text
VIMCMD=""   # Nach dem Hinzufuegen auszufuehrende Kommandos

#-------------------------------------------------------------------------------
# Alle notwendigen Programme vorhanden?
#-------------------------------------------------------------------------------
[ -z $(type -p perl    2> /dev/null) ] && echo "'perl' missing"    2>&1 && exit 1
[ -z $(type -p w3m     2> /dev/null) ] && echo "'w3m' missing"     2>&1 && exit 1
[ -z $(type -p wget    2> /dev/null) ] && echo "'wget' missing"    2>&1 && exit 1
[ -z $(type -p iconv   2> /dev/null) ] && echo "'iconv' missing"   2>&1 && exit 1
[ -z $(type -p sed     2> /dev/null) ] && echo "'sed' missing"     2>&1 && exit 1
[ -z $(type -p tidy    2> /dev/null) ] && echo "'tidy' missing"    2>&1 && exit 1
[ -z $(type -p $EDITOR 2> /dev/null) ] && echo "'$EDITOR' missing" 2>&1 && exit 1

#-------------------------------------------------------------------------------
# Debugausgaben
#-------------------------------------------------------------------------------
function Debug()
{
	echo "LANGUAGE    $LANGUAGE"
	echo "TYPE:       $TYPE"
	echo "LOCALFOUND: $LOCALFOUND"
	echo "LOCALDICT:  $LOCALDICT"
	echo "EDITOR:     $EDITOR"
	echo "LEOQUERY:   $LEOQUERY"
	echo "DICTQUERY:  $DICTQUERY"
	echo "LEOFILE:    $LEOFILE"
	echo "DICTFILE:   $DICTFILE"
	echo "DICTS:      $DICTS"
	echo "CMDFILE:    $CMDFILE"
	echo "VIMADD:    " && echo "$VIMADD" | od -c
	echo "VIMCMD:    " && echo "$VIMCMD" | od -c
}
#-------------------------------------------------------------------------------
# Fehler- + Usage-Meldung anzeigen und Programm abbrechen
#-------------------------------------------------------------------------------
function Usage
{
	exec 1>&2
	[ "$1" ] && echo "ERROR: $1"
	echo "USAGE: translate.sh [OPTION...] WORT/BEGRIFF"
	echo "       Begriff (deu/eng) gemaess Remote-Woerterbuechern '$LEOFQDN'" und
	echo "       '$DICTFQDN' bzw. lokalem WB '$LOCALDICT'" uebersetzen
	echo "       und neue Uebersetzung in lokales WB aufnehmen + ggfs. editieren"
	echo "OPTION:  -a  ALLE WB durchsuchen + NEUES Wort zu LOK. WB + edit. [add]"
	echo "         -b  ALLE WB durchsuchen [both]"
	echo "         -d  Debugging einschalten, temp. Dateien stehen lassen [debug]"
	echo "         -e  LOKALES WB editieren [edit]"
	echo "         -f  ALLE WB durchsuchen + IMMER Wort zu LOK. WB + edit. [force, STD]"
	echo "         -h  Usage-Meldung anzeigen [help]"
	echo "         -l  NUR LOKALES WB durchsuchen [local]"
	echo "         -L  Sprache (ch,en,es,fr,it,pl,ru,uk) (STD: en) [Language]"
	echo "         -w  REMOTE WB auflisten [wordbook]"
	echo "         -x  NUR EXTERNE WB durchsuchen [extern]"
	[ "$DEBUG" ] && echo && Debug
	exit 1
}
#-------------------------------------------------------------------------------
# Lokal suchen und ausgeben + Status "0=Gefunden/1=Nicht gefunden" zurueck
#-------------------------------------------------------------------------------
function SearchLocal
{
	if grep -qi "$*" $LOCALDICT
	then
		echo "'$*' im lokalen Woerterbuch vorhanden!" 1>&2
		grep -i "$*" $LOCALDICT
		return 0
	else
		echo "'$*' nicht im lokalen Woerterbuch gefunden!" 1>&2
		return 1
	fi
}
#-------------------------------------------------------------------------------
# Ergebnis von Remote-Suche + Status "0=Gefunden/1=Nicht gefunden" zurueck
#-------------------------------------------------------------------------------
function SearchRemote
{
	if [ -s "$LEOFILE" -o -s "$DICTFILE" ]
	then
		cat $LEOFILE $DICTFILE
		return 0
	else
		echo "'$*' nicht remote gefunden!" 1>&2
		return 1
	fi
}
#-------------------------------------------------------------------------------
# Bekannte Optionen erkennen, falsche abfangen
#-------------------------------------------------------------------------------
while getopts ":abdefhlL:wx" OPT; do   # ":" am Anfang unterdrueckt Fehlermeldung
	case $OPT in                       # ":" nach Buchstabe heisst mit Parameter
		a) TYPE="add"    ;;
		b) TYPE="both"   ;;
		d) DEBUG="1"     ;;
		e) TYPE="edit"   ;;
		f) TYPE="force"  ;;
		h) Usage         ;;
		l) TYPE="local"  ;;
		L) LANGUAGE="$OPTARG" ;;
		w) TYPE="listwb" ;;
		x) TYPE="remote" ;;
		*) Usage "Option -$OPTARG nicht erlaubt (oder braucht Parameter)" ;;
	esac
done

# Gefundene Optionen aus Argumentlisten schieben
shift $(expr $OPTIND - 1)

# Erlaubte Sprache?
case "$LANGUAGE" in
	[Cc][HhNn]*|[Zz][Hh])    LANGUAGE="ch" ;;   # Chinesisch
	[Ee][Nn]*)               LANGUAGE="en" ;;   # Englisch
	[Ee][Ss]*|[Ss][Pp]*)     LANGUAGE="es" ;;   # Spanisch
	[Ff][Rr]*)               LANGUAGE="fr" ;;   # Franzoesisch
	[Ii][Tt]*)               LANGUAGE="it" ;;   # Italienisch
	[Pp][Ll]*|[Pp][Oo][Ll]*) LANGUAGE="pl" ;;   # Polnisch
	[Rr][Uu]*)               LANGUAGE="ru" ;;   # Russisch
	[Uu][Kk]*)               LANGUAGE="uk" ;;   # Ukrainisch
	*) Usage "Sprache '$LANGUAGE' nicht erlaubt" ;;
esac

# URLs fuer Uebersetzung
  LEOURL="http://${LEOFQDN}/?lp=${LANGUAGE}de&cmpType=relaxed&sectHdr=on&spellToler=oniacritic&relink=on&search="
 DICTURL="http://${DICTFQDN}/?s="

# Lokales Woerterbuch fuer Uebersetzung
LOCALDICT="$HOME/.translate.$LANGUAGE"
  LOCKDIR="$HOME/.translate.$LANGUAGE.lock"

# Liste aller Woerterbuecher
DICTS="$LEOFQDN\n$DICTFQDN\n$LOCALDICT"

# Woerterbuecher auflisten? -> Liste + Abbruch
[ "$TYPE" == "listwb" ] && echo -e "$DICTS" && exit 0

# Kein Begriff angegeben? -> Abbruch
[ "$TYPE" != "edit" -a $# -eq 0 ] && Usage "Begriff fehlt"
[ "$TYPE" != "edit" -a $# -gt 1 ] && Usage "Nur einen Begriff angeben"

# Pruefungen
[ -f "$LOCALDICT" ] || Usage "Lokales Woerterbuch '$LOCALDICT' fehlt"
[ -r "$LOCALDICT" ] || Usage "Lokales Woerterbuch '$LOCALDICT' nicht lesbar"
[ -w "$LOCALDICT" ] || Usage "Lokales Woerterbuch '$LOCALDICT' nicht schreibbar"
[ -e "$LOCKDIR"   ] && Usage "Lockvzer. '$LOCKDIR' existiert, bitte nochmal"
#-------------------------------------------------------------------------------
# ping mit Option -W statt -w wg. Apple-Darwin 
#-------------------------------------------------------------------------------
#[ "$DEBUG" ] && ping -w3 -c1 $LEOFQDN
[ "$DEBUG" ] && ping -W3 -c1 $LEOFQDN
# ping -w3 -c1 $LEOFQDN > /dev/null 2>&1 ||
# ping -W3 -c1 $LEOFQDN > /dev/null 2>&1 ||
wget -O - $LEOFQDN > /dev/null 2>&1 ||
                       Usage "Leo-Server '$LEOFQDN' nicht erreichbar"
#[ "$DEBUG" ] && ping -w3 -c1 $DICTFQDN
[ "$DEBUG" ] && ping -W3 -c1 $DICTFQDN
#ping -w3 -c1 $DICTFQDN > /dev/null 2>&1 ||
#ping -W3 -c1 $DICTFQDN > /dev/null 2>&1 ||
wget -O - $DICTFQDN > /dev/null 2>&1 ||
                       Usage "Dict-Server '$DICTFQDN' nicht erreichbar"

# Temporaere Dateien anlegen und am Skriptende loeschen
[ "$DEBUG" ] && rm -rf /tmp/leo.*
[ "$DEBUG" ] && rm -rf /tmp/dict.*
[ "$DEBUG" ] && rm -rf /tmp/cmd.*
 LEOFILE=$(mktemp "/tmp/leo.XXXXXXXX")  || exit 1
DICTFILE=$(mktemp "/tmp/dict.XXXXXXXX") || exit 1
 CMDFILE=$(mktemp "/tmp/cmd.XXXXXXXX")  || exit 1
[ "$DEBUG" ] || trap "rm -rf $LOCKDIR $LEOFILE $DICTFILE $CMDFILE 2> /dev/null" EXIT
[ "$DEBUG" ] && trap "rm -rf $LOCKDIR 2> /dev/null" EXIT

#-------------------------------------------------------------------------------
# LEO.ORG abfragen
#-------------------------------------------------------------------------------
if [ "$TYPE" = "remote" -o \
     "$TYPE" = "both" -o \
     "$TYPE" = "add" -o \
     "$TYPE" = "force" ]
then
	# URL aus zu uebersetzendem Begriff zusammenbauen (dabei Sonderzeichen
	# in Codierung iso8859-1 umwandeln und % + & in URL-Codierung %25 + %26)
	# Alternativ "utf-8"
	TOPIC="$(echo "$*" |
		iconv -f $(locale charmap) -t iso8859-1 |
		sed 's/%/%25/g; s/&/%26/g')"

	LEOQUERY="${LEOURL}${TOPIC}"
	[ "$DEBUG" ] && echo "DEBUG: wget '$LEOQUERY'"

	# HTTP-Abfrage durchfuehren und nur relevante Teile ausschneiden,
	# (d.h. irrelevante Teile wie Rahmen mit Menues, Werbung, ... weglassen):
	# + Weiterzuverarbeitende Teile:
	#   - Von 1.Zl bis "<body " am Zl.anfang
	#   - EINE Zeile mit Text 'id="contentholder"' = Ergebnistabelle
	#     (besser als sprachabh. "search results" oder "treffer" abzufragen)
	#   - Von Zeile mit </body> bis letzte Zeile $
	wget --proxy="on" \
	     --no-netrc \
	     --quiet \
	     --output-document="/dev/stdout" \
	     --user-agent="" \
	     "$LEOQUERY" | tee /tmp/leo.query |
		#tidy | tee /tmp/leo.tidy |
		# sed	-n '/id="contentholder"/p' |
		# HTML-Ergebnis in ASCII-Format (Latin1) umwandeln (-O UTF-8 + sed -> PENG!)
		w3m -T "text/html" -I "UTF-8" -O "latin1" -dump | tee /tmp/leo.ascii |
		perl -e '
			while (<STDIN>)
			{
				# Irrelevantes Anfangs- und Endstueck ignorieren
				next if 1 .. /(Direct Matches|Unmittelbare Treffer)/i;
				next if /Informationen aus dem Umfeld der Suche/i .. eof();

				# Irrelevante Zeilen ignorieren
				next if /^\s*$/;                                  # Leerzeile
				next if /^[|+-]+$/;                               # Trennzeile
				next if /^ *Substantive +\(\d+.*\d+\)/i;          # Zeile
				next if /^ *Verben +\(\d.*\d\)/i;                 # Zeile
				next if /^ *Adjektive.Adverbien +\(\d+.*\d+\)/i;  # Zeile
				next if /^ *Wendungen.Ausdrücke +\(\d+.*\d+\)/i;  # Zeile
				next if /^ *Keine Grundformen ableitbar/i;        # Zeile
				next if /^ *Weitere Treffer/i;                    # Zeile
				next if /^ *Beispiele/i;                          # Zeile
				next if /^ *mehr >>/i;                            # Zeile

				# Irrelevanten Leerraum entfernen
				# (Trennspalten unterschiedlicher Form weglassen)
				s/^\| *\| *//;
				s/^\|\[ *\] *\| *//;
				s/\|[i] *\| *//;
				s/\|( +)\|/ $1 /g;
				s/[ \t]*$//;
				s/ *\| */, /g;

				# Irrelevante Textstuecke entfernen
				s/( *)\[aviat\.\]( *)/$1        $2/g;
				s/( *)\[bank\.\]( *)/$1       $2/g;
				s/( *)\[coll\.\]( *)/$1       $2/g;
				s/( *)\[constr\.\]( *)/$1         $2/g;
				s/( *)\[econ\.\]( *)/$1       $2/g;
				s/( *)\[elec\.\]( *)/$1       $2/g;
				s/( *)\[finan\.\]( *)/$1       $2/g;
				s/( *)\[med\.\]( *)/$1      $2/g;
				s/( *)\[pharm\.\]( *)/$1        $2/g;
				s/( *)\[print\.\]( *)/$1        $2/g;
				s/( *)\[tech\.\]( *)/$1       $2/g;
				s/( *)\[textil\.\]( *)/$1         $2/g;
				s/( *)\[telecom\.\]( *)/$1          $2/g;
				s/\b(der|die|das)\b[ \t]*//;
				s/ *\{([nfm]|pl)\} */ /g;

				# Zeile merken
				push @_, $_;
			}

			# Zeilen zu einem String verketten (Newlines erhalten)
			$_ = join("", @_);

			# Irrelevante Zahlen und Zeilenvorschuebe entfernen
			s/ *\n +/ /gms;
			s/\[\n */[/gms;
			s/ *\n\[/ [/gms;

			# Sonderzeichen durch Leerzeichen ersetzen
			s/[^ -~äöüÄÖÜß\n]/ /g;

			print;
		' > $LEOFILE

#	# Ergebnisdatei leeren falls nichts passendes in LEO gefunden
#	egrep -qi "(direct  *matches|composed  *entries)" $LEOFILE ||
#		echo -n > $LEOFILE

#-------------------------------------------------------------------------------
# DICT.CC abfragen
#-------------------------------------------------------------------------------

	DICTQUERY="${DICTURL}${TOPIC}"
	[ "$DEBUG" ] && echo "DEBUG: wget '$DICTQUERY'"

	# HTTP-Abfrage durchfuehren und nur relevante Teile ausschneiden
	# (d.h. irrelevante Teile wie Rahmen mit Menues, Werbung, ... weglassen):
	wget --proxy="on" \
	     --no-netrc \
	     --quiet \
	     --output-document="/dev/stdout" \
	     --user-agent="" \
	     "$DICTQUERY" | tee /tmp/dict.query |
		# tidy | tee /tmp/dict.tidy |
		# HTML-Ergebnis in ASCII-Format (Latin1) umwandeln (-O UTF-8 + sed -> PENG!)
		w3m -T "text/html" -I "UTF-8" -O "latin1" -dump | tee /tmp/dict.ascii |
		perl -e '
			while (<STDIN>)
			{
				# Irrelevantes Anfangs- und Endstueck ignorieren
				next if 1 .. /Wörterbuch.*Übersetzung/;
				next if /Unter folgender Adresse kannst du/ .. eof();

				# Irrelevante Zeilen ignorieren
				next if /^\s*$/;                          # Leerzeile
				next if /^-+$/i;                          # Trennlinie
				next if /OpenThesaurus\.de/i;             # Zeile
				next if /Princeton University/i;          # Zeile
				next if /^ *\d+ *Wörter/i;                # Zeile
				next if /^Substantive$/i;                 # Zeile
				next if /Weitere \d+ *Übersetzungen/i;    # Zeile

				# Irrelevante Textstuecke entfernen
				s/^ *edit *//;
				s/ *\[pxl\] *//g;
				s/SYNO *//;
				s/NOUN *//;
				s/( *)\[geh\.\]( *)/$1      $2/g;
				s/( *)\[ugs\.\]( *)/$1      $2/g;
				s/ *\{([nfm]|pl)\} */ /g;

				# Irrelevanten Leerraum entfernen
				s/( {2,})\| /$1/g;
				s/ *\| */, /g;
				s/^ {1,7}//;
				s/ *\* */   /;

				# Zeile merken
				push @_, $_;
			}

			# Zeilen zu einem String verketten (Newlines erhalten)
			$_ = join("", @_);

			# Irrelevante Zahlen und Zeilenvorschuebe entfernen
			s/\d+ *\n *//gms;
			s/ *\n +/ /gms;

			# Sonderzeichen durch Leerzeichen ersetzen
			s/[^ -~äöüÄÖÜß\n]/ /g;

			print;
		' > $DICTFILE

#-------------------------------------------------------------------------------
# Editorbefehle erstellen
#-------------------------------------------------------------------------------

	# LEO/DICT-Ergebnis vorhanden? -> VIM-Kommandos zum Anhaengen erstellen
	# :g/TOPIC/m $^M = Zeilen mit TOPIC ans Dateiende verschieben
	# G              = Sprung an Dateiende
	# my             = Marke "y" setzen
	# o=== DICT.CC = = Text anhaengen
	# :$rLEOFILE^M   = Dateiinhalt danach einfuegen (neue Zeilen darunter)
	# G              = Sprung an Dateiende
	# o=== LEO.ORG = = Text anhaengen
	# :$rDICTFILE^M  = Dateiinhalt danach einfuegen (neue Zeilen darunter)
	# 1G             = Zum Dateianfang gehen
	# /TOPIC/^M      = 1. Zeile mit TOPIC suchen (alle nach unten verschoben)
	# z^M            = Aktuelle Zeile zur 1. Bildschirmzeile machen
	# 'y             = Zur Zeile mit Marke "y" springen
	# 3k3j           = 3 Zeilen rauf + runter = 3 Zeilen oberhalb sichtbar machen
	# $              = Zum Zl.ende springen
	if [ -s "$LEOFILE" -o -s "$DICTFILE" ]
	then
		VIMCMD=':g/'"$TOPIC"'/m $'
		VIMCMD="$VIMCMD"'G'
		VIMCMD="$VIMCMD"'my'
		if [ -s "$LEOFILE" ]
		then
			VIMCMD="$VIMCMD"'o======== LEO.ORG ========'
			VIMCMD="$VIMCMD"':$r'"$LEOFILE"''
			VIMCMD="$VIMCMD"'G'
		fi
		if [ -s "$DICTFILE" ]
		then
			VIMCMD="$VIMCMD"'o======== DICT.CC ========'
			VIMCMD="$VIMCMD"':$r'"$DICTFILE"''
			VIMCMD="$VIMCMD"'1G'
		fi
		VIMCMD="$VIMCMD""'y"
		VIMCMD="$VIMCMD"'z'
		VIMCMD="$VIMCMD"'3k'
		VIMCMD="$VIMCMD"'3j'
		VIMCMD="$VIMCMD"'$'
		VIMCMD="$VIMCMD"'a'
	fi
fi

#-------------------------------------------------------------------------------
# Suchen/Editieren durchfuehren je nach Option
#-------------------------------------------------------------------------------
mkdir $LOCKDIR || Usage "Kann Lockverz. '$LOCKDIR' nicht anlegen"

case "$TYPE" in
	local)  SearchLocal "$*" | less
			;;
	remote) SearchRemote "$*" | less
			;;
	both)   (SearchRemote "$*";         # 1. da evtl. sehr lang
			SearchLocal "$*") | less   # 2. da fast immer kurz
			;;
	edit)   if [ -n "$*" ]
			then
				# Woerterbuch Editieren? -> Zum unteren rechte Ende springen
				VIMADD="$(printf "Go%-${LEFTCOLWIDTH}s" "$*")"
			fi
			if [ "$EDITOR" = vim ]
			then
				echo -n "${VIMADD}${VIMCMD}" > $CMDFILE
				$EDITOR -s "$CMDFILE" $LOCALDICT
			else
				$EDITOR $LOCALDICT
			fi
			;;
	add)    if ! SearchLocal "$*"
			then
				# Woerterbuch Editieren? -> Zum unteren rechte Ende springen
				VIMADD="$(printf "Go%-${LEFTCOLWIDTH}s" "$*")"
				if ! SearchRemote "$*"
				then
					# Nicht gefunden? -> Hinweistext unten rechts anfuegen
					VIMADD="${VIMADD}A??? Weder lokal noch remote gefunden!"
					# Alle Zeilen mit TOPIC drin nach unten verschieben
					# :g/TOPIC/m $^M = Zeilen mit TOPIC ans Dateiende verschieben
					# G              = Sprung an Dateiende
					# z^M            = Aktuelle Zeile zur 1. Bildschirmzeile machen
					# 3k3j           = 3 Zeilen rauf + runter = 3 Zeilen oberhalb sichtbar machen
					# $              = Zum Zl.ende springen
					# ?\?\?\?^M      = Von hinten nach "???" suchen
					VIMCMD=':g/'"$TOPIC"'/m $Gz3k3j$?\?\?\?'
				fi
				if [ "$EDITOR" = vim ]
				then
					echo -n "${VIMADD}${VIMCMD}" > $CMDFILE
					$EDITOR -s "$CMDFILE" $LOCALDICT
				else
					$EDITOR $LOCALDICT
				fi
			fi
			;;
	force)  SearchLocal "$*"
			LOCALFOUND=$?
			VIMADD="$(printf "Go%-${LEFTCOLWIDTH}s" "$*")"
			if ! SearchRemote "$*"
			then
				if [ "$LOCALFOUND" = 0 ]
				then
					# Remote nicht gefunden? -> Hinweistext unten rechts anfuegen
					VIMADD="${VIMADD}A??? Remote nicht gefunden!"
				else
					# Nicht gefunden? -> Hinweistext unten rechts anfuegen
					VIMADD="${VIMADD}A??? Weder lokal noch remote gefunden!"
				fi
				VIMCMD=':g/'"$TOPIC"'/m $Gz3k3j$?\?\?\?'
			fi
			if [ "$EDITOR" = vim ]
			then
				echo -n "${VIMADD}${VIMCMD}" > $CMDFILE
				$EDITOR -s "$CMDFILE" $LOCALDICT
			else
				$EDITOR $LOCALDICT
			fi
			;;
esac

[ "$DEBUG" ] && echo && Debug
