% \iffalse ********************************************* METACOMMENT % % TeX this file with LaTeX2e ! % % The following files will be written: % % ==> bulkmail.dvi Documentation (read this first) % % --> bulkmail.sty package file % %% Copyright : Kai-Uwe Bux %% --------- Norderneystraße 26 %% D-26419 Schortens/Heidmühle (Germany) %% %% ***************************************************************** % >>>>>>>>> !! Proliferation of UNCHANGED versions of !! <<<<<<<<< % !! this file is permitted !! % % >>>>>>>>> !! Don't change this file without changing !! <<<<<<<<< % !! it's name !! % ****************************************************************** % % \begin{macrocode} \def\FileVersion{0.20b $\beta$-Test} \def\FileDate{2001/01/10} \def\FileDescription{Serienbriefe mit LaTeX} % \end{macrocode} % % ********************************************** END METACOMMENT \fi % % \CheckSum{237} % \StopEventually{} % % \iffalse ********************************************* METACOMMENT % \begin{macrocode} %<*driver> \NeedsTeXFormat{LaTeX2e}[1995/12/01] \let\ThisVersion\FileVersion \let\ThisDate\FileDate % % \end{macrocode} % ********************************************** END METACOMMENT \fi % % \iffalse ******************************************** METATCOMMENT % % Dieser Abschnitt erscheint nicht in der Dokumentation % % \Section{Installation} % Der folgende Kode ist etwas trickreich. % \begin{macrocode} %<*installation> \ifx\undefined\batchfile\begingroup\fi \makeatletter \def\batchfile{bulkmail.dtx} \def\g{\generateFile{bulkmail.sty}{f}{\from{bulkmail.dtx}{package}}\let\g\relax} \def\s{\endinput\let\s\relax} \let\@@end=\relax \input docstrip.tex \g\s \endgroup % \end{macrocode} % Jetzt ist die Paket-Datei \file{bulkmail.sty} auf der Platte. % % Kommen wir nun zum Inhaltsverzeichnis und der Hilfsdatei: % \begin{macrocode} \begin{filecontents}{bulkmail.toc} \IfFileExists{babel.sty}{% \select@language {german} }{} \contentsline {section}{\numberline {1}Wie man einen Serienbrief erstellt}{1} \contentsline {subsection}{\numberline {1.1}Was man bisher tun mu"ste}{1} \contentsline {subsection}{\numberline {1.2}Der Aufbau eines Serienbriefes}{2} \contentsline {subsection}{\numberline {1.3}Ein einfaches Beispiel}{2} \contentsline {subsection}{\numberline {1.4}Die vollst"andige Beschreibung aller Macros}{4} \contentsline {subsubsection}{\numberline {1.4.1}Pr"aambelbefehle}{4} \contentsline {subsubsection}{\numberline {1.4.2}Die Serienbriefumgebung}{4} \contentsline {subsubsection}{\numberline {1.4.3}Textbausteine}{5} \contentsline {subsection}{\numberline {1.5}"Ubersicht "uber alle Befehle}{7} \contentsline {section}{\numberline {2}Implementation des Pakets}{8} \contentsline {subsection}{\numberline {2.1}Identifikation}{8} \contentsline {subsection}{\numberline {2.2}Zu ladende Pakete}{8} \contentsline {subsection}{\numberline {2.3}Die Erzeugung der Empf"angerliste}{8} \contentsline {subsection}{\numberline {2.4}Die Briefe}{9} \contentsline {subsection}{\numberline {2.5}Einladen von Verteilerdateien}{12} \contentsline {subsection}{\numberline {2.6}Kleinere Hilfen}{12} \end{filecontents} \begin{filecontents}{bulkmail.aux} \relax \IfFileExists{babel.sty}{% \select@language{german} \@writefile{toc}{\select@language{german}} \@writefile{lof}{\select@language{german}} \@writefile{lot}{\select@language{german}} }{} \@writefile{toc}{\contentsline {section}{\numberline {1}Wie man einen Serienbrief erstellt}{1}} \@writefile{toc}{\contentsline {subsection}{\numberline {1.1}Was man bisher tun mu"ste}{1}} \@writefile{toc}{\contentsline {subsection}{\numberline {1.2}Der Aufbau eines Serienbriefes}{2}} \@writefile{toc}{\contentsline {subsection}{\numberline {1.3}Ein einfaches Beispiel}{2}} \@writefile{toc}{\contentsline {subsection}{\numberline {1.4}Die vollst"andige Beschreibung aller Macros}{4}} \@writefile{toc}{\contentsline {subsubsection}{\numberline {1.4.1}Pr"aambelbefehle}{4}} \@writefile{toc}{\contentsline {subsubsection}{\numberline {1.4.2}Die Serienbriefumgebung}{4}} \@writefile{toc}{\contentsline {subsubsection}{\numberline {1.4.3}Textbausteine}{5}} \@writefile{toc}{\contentsline {subsection}{\numberline {1.5}"Ubersicht "uber alle Befehle}{7}} \@writefile{toc}{\contentsline {section}{\numberline {2}Implementation des Pakets}{8}} \@writefile{toc}{\contentsline {subsection}{\numberline {2.1}Identifikation}{8}} \@writefile{toc}{\contentsline {subsection}{\numberline {2.2}Zu ladende Pakete}{8}} \@writefile{toc}{\contentsline {subsection}{\numberline {2.3}Die Erzeugung der Empf"angerliste}{8}} \@writefile{toc}{\contentsline {subsection}{\numberline {2.4}Die Briefe}{9}} \@writefile{toc}{\contentsline {subsection}{\numberline {2.5}Einladen von Verteilerdateien}{12}} \@writefile{toc}{\contentsline {subsection}{\numberline {2.6}Kleinere Hilfen}{12}} \end{filecontents} % % \end{macrocode} % Jetzt liegen die folgenden Dateien vor: % \begin{enumerate} % \item \file{bulkmail.dtx}, die Datei, die alles enth"alt. % \item \file{bulkmail.toc}, ihr Inhaltsverzeichnis. % \item \file{bulkmail.aux}, die Hilfsdatei. % \item \file{bulkmail.sty}, die Paket-Datei. % \end{enumerate} % Die \file{.sty}-Datei geh"ort in ein Verzeichnis, wo \TeX\ % nach Paketen sucht. % % ********************************************** END METACOMMENT \fi % % \iffalse ********************************************* METACOMMENT % % Dieser Abschnitt erscheint nicht in der Dokumentation % % \Section{Die Erzeugung der Dokumentation} % Nun liegen also alle Dateien vor. Jetzt sollte die Beschreibung % erfolgen. Zum Gl"uck k"onnen wir die Pakete schon benutzen. % Das folgende ist der Inhalt von \file{buxpkgs.drv}. Diese % Datei durch \LaTeX\ jagen! % \begin{macrocode} %<*driver> \documentclass[12pt]{ltxdoc} \IfFileExists{babel.sty}{% \usepackage[german]{babel} }{% \usepackage{german} } \newcommand{\pkg}[1]{\textsf{#1}} \newcommand{\cls}[1]{\textsf{#1}} \newcommand{\file}[1]{\texttt{#1}} \newcommand{\env}[1]{\texttt{#1}} \newcommand{\opt}[1]{\textsf{#1}} \newcommand{\sect}[1]{{#1}} \newcommand{\sty}[1]{\emph{#1}} \newcommand{\ARG}[1]{\emph{#1}} \newcommand{\GobbleOne}[1]{} \newcommand{\Section}{\newpage\section} \newcommand{\finalnopagebreak}{\nopagebreak} \newcommand{\finalpagebreak}{\pagebreak} \begin{document} \title{Serienbriefe mit \LaTeXe\\ Das \pkg{bulkmail}-Paket} \author{Kai-Uwe Bux} \date{\begin{tabular}{ll} Datum: & \ThisDate\\ Version: & \ThisVersion \end{tabular}} \maketitle\thispagestyle{empty}\tableofcontents\newpage \setcounter{page}{1}\DocInput{bulkmail.dtx} \end{document} % % \end{macrocode} % % ********************************************** END METACOMMENT \fi % % \Section{Wie man einen Serienbrief erstellt} % \subsection{Was man bisher tun mu"ste} % Nat"urlich kann man mit \LaTeX\ Serienbriefe erstellen. Der Trick, der % am weitesten verbreitet sein d"urfte, ist der, der einem als erster in % den Sinn kommt: % \begin{enumerate} % \item % Man schreibt den eigentlichen Brief in eine Datei, % sagen wir \file{ltrbody.tex}, die ungef"ahr so aussieht: % \begin{verbatim} % \opening{...} % ... % \closing{...} % \end{verbatim} % \item % Man schreibt ein Macro, sagen wir |\brief|, mit einem Argument: % \begin{verbatim} % \newcommand{\brief}[1]{\begin{letter}{#1} % \input{ltrbody.tex} % \end{letter}} % \end{verbatim} % \item % In der Datei, die den Serienbrief erzeugen soll, schreibt man: % \begin{verbatim} % \documentclass[...]{letter} % ... % \begin{document} % \brief{...} % \brief{...} % ... % \end{document} % \end{verbatim} % \end{enumerate} % Dieses Vorgehen ist auch gar nicht schlecht. Aber eine befriedigende % L"osung ist es nicht, weil man gezwungen ist, die Information "uber die % Empf"anger in einer anderen Datei unterzubringen als den Text des % Schreibens. Besser w"are es doch, wenn man einen Serienbrief wie einen % ganz normalen Brief schreiben k"onnte. Das vorliegende Paket % \pkg{bulkmail} leistet genau dies. % % Wichtig in diesem Zusammenhang ist folgendes: % das \pkg{bulkmail}-Paket nimmt keine Ver"anderungen im Layout von Briefen % vor, hindert andere Pakete jedoch nicht, dies zu tun. Wenn also ein % lokales Brief-Paket verwendet wird, so d"urfte dies zu keinen % Problemen f"uhren. Das \pkg{bulkmail}-Paket verwendet die aktuelle % \env{letter}-Umgebung einschlie"slich aller Modifikationen, die andere % Pakete oder Klassen daran vornehmen m"ogen. % % \subsection{Der Aufbau eines Serienbriefes} % Grunds"atzlich besteht eine Serienbriefdatei aus einer Liste von % Empf"angern und einer Liste von Schreiben, die diesen zugehen sollen. % Der Aufbau ist also: % \begin{verbatim} % \documentclass[...]{letter} % ... % \usepackage{bulkmail} % ... % \SendTo{...}{...} % \SendTo{...}{...} % \IncludeAddressFile{...} % \begin{document} % \begin{bulkmail} % ... % \end{bulkmail} % \end{document} % \end{verbatim} % Dabei steht im zweiten Argument von |\SendTo| genau das, was man sonst % in das % Argument der \env{letter}-Umgebung geschrieben h"atte. An deren Stelle % tritt die \env{bulkmail}-Umgebung, in der alles erlaubt ist, was in % einer \env{letter}-Umgebung an dieser Stelle erlaubt w"are. % % Mit |\IncludeAddressFile| kann eine Datei, die ihrerseits wieder % |\SendTo|- oder |\IncludeAddressFile|-Befehle enthalten kann, geladen % werden. Die so angegebenen Empf"anger werden ebenfalls % ber"ucksichtigt. \emph{Wird ein Empf"anger mehrfach angegeben, so % werden mehrere Briefe ausgegeben.} % % \subsection{Ein einfaches Beispiel} % Nehmen wir den einfachen Fall, jemand wollte die "Anderung seiner % Anschrift seinen Bekannten mitteilen. Folgende Datei k"onnte das % bewerkstelligen: % \begin{verbatim} % \documentclass[11pt,german]{letter} % \usepackage{babel} % \usepackage{myletter} % \usepackage{bulkmail} % % \date{29.~Februar~1996} % \SendTo{\male % \familyname{M"uller} % \firstname[H.]{Hans} % }{Herrn \printname\\ % Gute Mine 51\\[2mm] % 66666 Im b"osen Spiel} % \SendTo{\female % \familyname{Hutschen} % \firstname[M.]{Marie} % \secondname[R.]{Ruth} % }{Frau \printname\\ % Im Tief 5\\[2mm] % 24756 Ollsted} % \IncludeAddressFile{verein} % % \begin{document} % \begin{bulkmail} % \opening{\iffemale % Sehr geehrte Frau \longfamilyname, % \fi % \ifmale % Sehr geehrter Herr \longfamilyname, % \fi} % Ich m"ochte mir erlauben, Ihnen mitzuteilen, da"s sich meine % Adresse ge"andert hat. Bitte schreiben Sie mir k"unftig an % folgende Anschrift: % \begin{quote} % Hajo Hobbes\\ % Auf dem Weg 12\\[2mm] % 34567 Posemuckel % \end{quote} % \closing{Hochachtungsvoll\\ % Ihr} % \end{bulkmail} % \end{document} % \end{verbatim} % Mit |\usepackage{bulkmail}| wird das Paket \pkg{bulkmail} geladen. % Die |\SendTo|-Befehle deklarieren die Adressaten. |\female|, % |\male|, |\familyname| etc.\ sind Macros, die bei der % Angabe der Adressaten % benutzt werden k"onnen. Sie definieren dabei zugleich weitere % Macros wie |\longfamilyname| oder |\||ifmale|, die im Brief % genutzt werden k"onnen, um Empf"anger richtig anzusprechen. % Wie das geschieht, ist im Argument von |\opening| zu sehen. % |\IncludeAddressFile| l"adt die Datei \file{verein.tex} als % ">Verteiler"<. % Den Text des Briefes gibt man innerhalb der \env{bulkmail}-Umgebung % an. % % \subsection{Die vollst"andige Beschreibung aller Macros} % \subsubsection{Pr"aambelbefehle} % Das Macro |\SendTo| hat zwei obligatorische % Argumente. Das letztere gibt den Empf"anger an. Es enth"alt also, % was sonst das Argument der \env{letter}-Umgebung w"are. % Das vorausgehende Argument kann beliebigen Code % beinhalten, der vor dem Setzen des jeweiligen Briefes ausgef"uhrt % wird. Darin k"onnen insbesondere Textbausteine, die von % Empf"anger zu Empf"anger wechseln, spezifisch definiert werden. % % Das Macro |\IncludeAddressFile| dient dazu einen ">Verteiler"< % einzubinden. Das ist eine Datein, die eine Liste von |\SendTo|- % und |\IncludeAddressFile|-Befehlen enth"alt. Wichtig zu wissen % ist zweierlei: % \begin{itemize} % \item % Ein Verteiler wird mit |\InputIfFileExists| eingelesen und % ist in diesem Augenblick eine ganz normale \TeX{}datei, so da"s % er also insbesondere |\||if|-Abfragen enthalten kann, durch % die die Auswahl der Empf"anger gesteuert werden kann. % \item % Dabei ist jedoch folgendes zu beachten: % der Verteiler wird erst beim Setzen der Serienbriefe % geladen, und nicht etwa zum % Zeitpunkt der Expansion von |\IncludeAddressFile|. % \end{itemize} % % Es gibt noch ein weiteres Macro, das nur in der Pr"aambel % vorkommen darf. Es hei"st |\DeclareBulkmailCommand| und erlaubt % dem Nutzer, auf komfortable Weise Macros f"ur Textbausteine % zu definieren. Es wird weiter unten ausf"uhrlich beschrieben. % % \subsubsection{Die Serienbriefumgebung} % Die \env{bulkmail}-Umgebung tritt an die Stelle der % \env{letter}-Umgebung. Sie ruft diese intern auf, so da"s % im Prinzip keine Probleme bei der gleichzeitigen Verwendung % von Paketen, die das Layout von Briefen ver"andern, bestehen % d"urften. Das \pkg{bulkmail}-Paket ist kompatibel mit jedem % Layout. Innerhalb der \env{bulkmail}-Umgebung stehen alle % Befehle zur Verf"ugung, die in einer \env{letter}-Umgebung % benutzbar w"aren. % % Intern benutzt die \env{bulkmail}-Umgebung die von Rainer~Sch"opf, % Bernd~Raichle und Chris~Rowley neu implementierte % \env{verbatim}-Umgebung. Man mu"s darum nach |\end{bulkmail}| % eine neue Zeile anfangen. Diese Einschr"ankung gilt auch f"ur alle % anderen \env{verbatim}-basierten Umgebungen in dem entsprechenden % Dokument. % % \subsubsection{Textbausteine} % Obschon das erste Argument von |\SendTo| eine % geeignete Stelle ist, Textbausteine empf"angerabh"angig zu % definieren, gibt es bestimmte immer wieder auftretende % Situationen, f"ur die eine bequemere L"osung w"unschenswert % w"are. Die Anrede ist so ein Fall. Sie wechselt in der Regel % mit dem Namen und dem Geschlecht des Adressaten. % % Die Macros |\female| und |\male| setzen zun"achst die Variablen % |\||iffemale| und |\||ifmale| auf die richtigen Werte. % Dann gibt es noch die folgenden Macros: % \begin{itemize} % \item[]|\firstname| : Vorname % \item[]|\secondname| : Zwischenname % \item[]|\familyname| : Nachname % \item[]|\nickname| : Spitzname % \item[]|\degree| : Titel und akademische Grade. % \end{itemize} % Diese Macros sind einander sehr "ahnlich. % Jedes dieser Macros hat ein optionales und ein obligatorisches % Argument. Das optionale dient dazu, eine eventuelle Abk"urzung % anzugeben und wird in \emph{eckige} Klammern "`[\ldots ]"' % eingeschlossen. Ein Beispiel w"are also: % \begin{verbatim} % \SendTo{\male % \familyname{Aschendorfer} % \degree[Prof.]{Prof.~Dr.} % \firstname[H.]{Herbert} % }{Herrn \printname\\ % ...} % \end{verbatim} % Was tun diese Macros mit ihren Argumenten? Sie speichern sie % zur sp"ateren Verwendung im Text. Dabei definiert das Macro % |\macro| die Langform |\longmacro| und, falls ein optionales % Argument "ubergeben wird, die Kurzform |\shortmacro|. % Mit anderen Worten durch die Zeile % \begin{verbatim} % \familyname{Aschendorfer} % \end{verbatim} % wird das Macro |\longfamilyname| so definiert, da"s es zu % ">\texttt{Aschendorfer}"< expandiert. Das Macro |\shortfamilyname| % hingegen bleibt undefiniert --- es ist |\undefined|. Die Zeile % \begin{verbatim} % \firstname[H.]{Herbert} % \end{verbatim} % definiert das Macro |\longfamilyname| als ">\texttt{Herbert}"< und % das Macro |\shortfamilyname| als ">\texttt{H.}"<. % % Nicht definierte Formen sind wie gesagt undefiniert. Man kann % also zu Konstruktionen wie der folgenden greifen: % \begin{verbatim} % ... % \ifx\longnickname\undefined % \longfirstname % \else % \longnickname % \fi % ... % \end{verbatim} % Das Macro |\printname| kann benutzt werden, um aus den Angaben % dann den Namen zusammenzusetzen. Es kann vom Benutzer in der % Pr"aambel umdefiniert werden, hat aber eine akzeptable % Voreinstellung, gem"a"s der Vor-, Zwischen- und Nachname gedruckt % werden, Titel und Spitznamen jedoch nicht dargestellt werden. % % Wenn einem Benutzer diese Macros nicht ausreichen, kann er sich % jederzeit neue Macros dieses Typs definieren. Dazu dient das % Deklarationsmacro |\DeclareBulkmailCommand|. Es kann nur in Paketen % oder der Pr"aambel benutzt werden. % Ein Beispiel mag verdeutlichen, worum es hierbei geht. % \begin{verbatim} % \documentclass[11pt,german]{letter} % \usepackage{babel} % \usepackage{lokalletter} % \usepackage{bulkmail} % ... % \DeclareBulkmailCommand{\mitgliedsnummer} % ... % \SendTo{\male % \familyname{Broter} % \firstname[M.]{Marie} % \mitgliedsnummer{123456} % }{Frau \printname\\ % ...} % ... % \end{verbatim} % Hier wird in der Zeile % \begin{verbatim} % \DeclareBulkmailCommand{\mitgliedsnummer} % \end{verbatim} % das Macro |\mitgliedsnummer| definiert. Es verh"alt sich nachher % ganz analog zu den oben besprochenen Macros |\familyname|, % |\firstname| etc. % % \subsection{"Ubersicht "uber alle Befehle} % Hier noch eine kleine Tabelle, damit man wei"s, welche % Benutzermacros das \pkg{bulkmail}-Paket bereitstellt. % \begin{description} % \item[Pr"aambelbefehle] % \item[ ] |\SendTo|, |\IncludeAddressFile|, |\DeclareBulkmailCommand| % \item[Umgebungen] % \item[ ] \env{bulkmail} % \item[Miszellen] % \item[ ] |\male|, |\female| % \item[ ] |\familyname|, |\firstname|, |\secondname|, % |\nickname|, |\degree| % \item[ ] |\printname| % \end{description} % % \StopEventually{} % \Section{Implementation des Pakets} % \subsection{Identifikation} % Dieses Paket meldet sich. %\iffalse %<*package> %\fi % \begin{macrocode} \@ifundefined{pkg@bulkmail}{\def\pkg@bulkmail{}}{\endinput} \NeedsTeXFormat{LaTeX2e}[1995/12/01] \typeout{Package: `bulkmail'. Version \FileVersion\space of \FileDate.} \ProvidesPackage{bulkmail}[\FileDate\space Serienbriefe mit LaTeX2e] % \end{macrocode} % % \subsection{Zu ladende Pakete} % Wir verwenden das \pkg{verbatim}-Paket, das im \file{tools}-B"undel % von \LaTeXe\ enthalten ist. Dieses Paket ist somit unter jeder % \LaTeXe-Installation verf"ugbar. % \begin{macrocode} \RequirePackage{verbatim} % \end{macrocode} % % \subsection{Die Erzeugung der Empf"angerliste} % Es gibt zwei Aufgaben. Zun"achst mu"s eine Liste der Empf"anger angelegt % werden. Dann mu"s f"ur jedes Element dieser Liste der Brief gesetzt % werden. % % Das Macro |\SendTo| dient dazu, einen Empf"anger in die Liste % aufzunehmen. Die Liste selbst ist ein Tokenregister |\ser@to|. % Darin sind die Empf"anger in folgendem Format gespeichert. % \begin{itemize} % \item Zu Anfang ist |\ser@to| leer. % \item Ein Aufruf von % \begin{quote} % |\SendTo{|\ARG{code}|}{|\ARG{Empf"anger}|}| % \end{quote} % h"angt die Folge % \begin{quote} % |\do@to{|\ARG{code}|}{|\ARG{Empf"anger}|}| % \end{quote} % an |\ser@to| an. % \end{itemize} % Das geschieht in der Pr"aambel eines Dokuments. Nachher steht diese % Liste allen Serienbriefen zur Verf"ugung. Durch geeignete Definition % von |\do@to| kann mit |\the\ser@to| ein Kommando auf alle Empf"anger % in der Reihenfolge ihrer Anmeldung angewendet werden. % % Zun"achst deklarieren und initialisieren wir die globale Variable % |\ser@to|: % \begin{macrocode} \newtoks\ser@to \ser@to={} % \end{macrocode} % Das Anh"angen geschieht durch einen % einfachen |\expandafter|-Trick. Das vordere |\expandafter| % sorgt daf"ur, da"s % das zweite Ausgef"uhrt wird. Und dieses "uberspringt dann die % Klammer "`|{|"'. Nachdem dann |\the\ser@to| expandiert ist, wird % die Klammer wieder davor gesetzt und |\ser@to| hat ein vollst"andiges % Argument. % \begin{macrocode} \newcommand{\SendTo}[2]{% \expandafter\ser@to\expandafter{\the\ser@to\do@to{#1}{#2}} } % \end{macrocode} % Und jetzt sorgen wir noch daf"ur, da"s |\SendTo| nur in der % Pr"aambel verwendet werden kann: % \begin{macrocode} \@onlypreamble\SendTo % \end{macrocode} % % \subsection{Die Briefe} % Ein Serienbrief steht in der \env{bulkmail}-Umgebung, die an die % Stelle der \env{letter}-Umgebung tritt. Im Unterschied zu dieser % hat sie allerdings kein Argument, da die Empf"anger ja in der % Pr"aambel angegeben werden. % % Die Idee, wie ein Serienbrief entsteht, ist folgende. Nehmen wir an, % jemand h"atte geschrieben: % \begin{verbatim} % \begin{bulkmail} % \opening{Hi \friend,} % ich wollte nur mitteilen, da"s sich meine Anschrift % ge"andert hat. Die neue ... % \closing{Mit freundlichen Gr"u"sen} % \end{bulkmail} % \end{verbatim} % Dann sollte |\do@to{|\ARG{code}|}{|\ARG{Empf"anger}|}| % in etwa expandieren zu: % \begin{quote} % |\begingroup|\\ % | |\ARG{code}|\relax|\\ % | \begin{letter}{|\ARG{Empf"anger}|}|\\ % | \opening{Hi \friend,}|\\ % | ich wollte nur mitteilen, da"s sich meine Anschrift|\\ % | ge"andert hat. Die neue ...|\\ % | \closing{Mit freundlichen Gr"u"sen}|\\ % | \end{letter}|\\ % |\endgroup| % \end{quote} % Der Aufruf von |\the\ser@to| h"atte dann zur Folge, da"s alle diese % Briefe gesetzt werden. Doch zum Aufbau ist noch ein wenig zu erkl"aren. % \begin{itemize} % \item % Die Einf"ugung von \ARG{code} an dieser Stelle soll es % erm"oglichen, die Variable |\friend| f"ur verschiedene % Addressaten geeignet zu definieren. % \item % |\relax| unterdr"uckt Leerzeichen. % \item % Die |\begingroup|\ldots|\endgroup|-Klammer dient dazu, diese % empf"angerspezifischen Definitionen lokal zu halten. % \end{itemize} % % So gut dieser Ansatz auch ist, es gibt damit noch ein paar technische % Probleme: % \begin{itemize} % \item % Tats"achlich ist die gro"se Preisfrage, wie man den Text des % Briefes in die Definition von |\do@to| reinbekommt. % \item % Selbst wenn dies gel"ange, w"urden lange Briefe \TeX{}s Speicher % "uberfordern. % \end{itemize} % Also gehen wir einen etwas anderen Weg. Die \env{bulkmail}-Umgebung % speichert den Text in der Datei |\jobname.bdy| zwischen. Dann mu"s % die Definition von |\do@to| wiefolgt lauten: % \begin{quote} % |\begingroup|\\ % | |\ARG{code}|\relax|\\ % | \begin{letter}{|\ARG{Empf"anger}|}|\\ % | \input\jobname.bdy|\\ % | \end{letter}|\\ % |\endgroup| % \end{quote} % Und genau das ist ziemlich genau, was wir tun werden. Tats"achlich % bauen wir statt des |\relax| nach \ARG{code} ein anderes Macro ein, % das uns sp"ater als Hook dienen wird. Und auch vor dem \ARG{code} und % ganz am Ende haben wir noch Hooks vorgesehen. % % Wie man den Inhalt einer Umgebung in eine Datei schreibt, kann man % in der Dokumentation des \pkg{verbatim}-Pakets nachlesen, das wir % f"ur diesen Zweck einsetzen. % % Jetzt frisch an's Werk. % Wir brauchen einen IO-Kanal zum Schreiben. % \begin{macrocode} \newwrite\ser@write % \end{macrocode} % Jetzt die \env{bulkmail}-Umgebung. % \begin{macrocode} \newenvironment{bulkmail}{% % \end{macrocode} % Die \env{bulkmail}-Umgebung setzt alle Catcodes jenseits 128 % auf 12~(other). % Ansonsten ist sie der \env{verbatimwrite}-Umgebung aus dem % \pkg{verbatim}-Paket nachgebildet. % \begin{macrocode} \begingroup \@tempcnta=128 \loop\ifnum\@tempcnta<256 \catcode\@tempcnta=12 \advance\@tempcnta\@ne \repeat \@bsphack \let\do\@makeother\dospecials \catcode`\^^M\active \immediate\openout\ser@write\jobname.bdy \def\verbatim@processline{% \immediate\write\ser@write{\the\verbatim@line}% } \verbatim@start }{% \immediate\closeout\ser@write \@esphack \endgroup % \end{macrocode} % Und jetzt noch der Trick, der daf"ur sorgt, da"s die Briefe % auch tats"achlich entstehen: % \begin{macrocode} \the\ser@to } % \end{macrocode} % % Das Macro |\do@to| hat die Form, die wir oben festgelegt % haben: % \begin{macrocode} \newcommand{\do@to}[2]{% \begingroup \ser@precode #1\ser@postcode \ser@preletter \begin{letter}{#2} \input\jobname.bdy \end{letter} \ser@postletter \endgroup } % \end{macrocode} % Und die Hooks m"ussen wir noch initialisieren: % \begin{macrocode} \newcommand{\ser@precode}{\relax} \newcommand{\ser@postcode}{\relax} \newcommand{\ser@preletter}{\relax} \newcommand{\ser@postletter}{\relax} % \end{macrocode} % % \subsection{Einladen von Verteilerdateien} % Das Macro |\IncludeAddressFile| liest eine Datei folgenden Formates % ein. F"ur jeden Empf"anger steht dort ein Eintrag der Form: % \begin{verbatim} % \SendTo{...}{...} % \end{verbatim} % Nat"urlich kann diese Tabelle auch einfach mit |\input| geladen werden. % Doch das hat zwei Nachteile: % \begin{itemize} % \item % Wird der Dateiname falsch geschrieben, erh"alt man diese % unfreundlichen Meldungen. % \item % Das Tokenregister |\ser@to| wird doch arg strapaziert. % \end{itemize} % Daher w"ahlen wir eine andere Implementation. |\IncludeAddressFile| % speichert lediglich einen Hinweis auf die Datei in |\ser@to|. % \begin{macrocode} \newcommand{\IncludeAddressFile}[1]{% \expandafter\ser@to\expandafter{\the\ser@to\ser@include{#1}} } \@onlypreamble\IncludeAddressFile % \end{macrocode} % % Beim Bearbeiten dieser Marke, bekommt |\SendTo| eine zeitweilige % neue Bedeutung. Man beachte, da"s diese Implementierung die M"oglichkeit % offenh"alt, |\IncludeAdressList| innerhalb solcher Verteiler zu % verwenden. % \begin{macrocode} \newcommand{\ser@include}[1]{% \begingroup \renewcommand{\SendTo}{% \do@to } \renewcommand{\IncludeAddressFile}[1]{% \InputIfFileExists{##1}{}{% \PackageWarning{bulkmail}{File `##1' not found}% }% }% \IncludeAddressFile{#1} \endgroup } % \end{macrocode} % % \subsection{Kleinere Hilfen} % Die Macros |\female| und |\male| dienen der Anrede. % \begin{macrocode} \newif\ifmale \newif\iffemale \DeclareRobustCommand{\male}{% \expandafter\global\maletrue } \DeclareRobustCommand{\female}{% \expandafter\global\femaletrue } \renewcommand{\ser@precode}{% \expandafter\global\femalefalse \expandafter\global\malefalse } % \end{macrocode} % Wir ben"otigen ein Macro, das die gleichf"ormige Implementierung % von |\familyname| etc.\ besorgt. Dazu einige Hilfmacros. Zuerst % |\ser@define|, das die eigentliche Arbeit von |\familyname| und % Konsorten "ubernehmen wird. % Dabzu dient ein kleiner Trick mit |\string| und |\escapechar|, der % in plain-\TeX{} bei der Definition von |\newif| auftaucht. % \begin{macrocode} \newcommand{\ser@define}[1]{% \@tempcnta\escapechar \escapechar=-1 \edef\@tempa{\string #1}% \escapechar\@tempcnta \@ifnextchar [{% \two@define }{% \one@define } } \newcommand{\two@define}[2][]{% \expandafter\newcommand\csname short\@tempa\endcsname{#1}% \expandafter\newcommand\csname long\@tempa\endcsname{#2}% \ignorespaces } \newcommand{\one@define}[1]{% \expandafter\newcommand\csname long\@tempa\endcsname{#1}% \ignorespaces } % \end{macrocode} % Damit w"are es leicht |\familyname| zu definieren als: % \begin{verbatim} % \newcommand{\familyname}{\ser@define{\familyname}} % \end{verbatim} % Und genau das m"ussen wir jetzt allgemein machen: % \begin{macrocode} \newcommand{\DeclareBulkmailCommand}[1]{% \newcommand{#1}{\ser@define{#1}} % \end{macrocode} % Das w"are alles, wenn wir nicht noch das Macro |\ser@precode| % anpassen m"u"sten. Da sollte n"amlich sowas stehen wie % \begin{verbatim} % \global\let\longfamilyname\undefined % \global\let\shortfamilyname\undefined % \end{verbatim} % Also m"ussen wir diesen Code an das Macro |\ser@precode| anh"angen. % Dazu verwenden wir |\edef| und die Eigenschaft von \TeX{}, da"s % Tokenregister nur eine First-Level-Expansion erleiden, wenn sie % im Replacementtext von |\edef| auftreten. Auch da"s |\expandafter| % nur eine First-Level-Expansion bewirkt, geht in diese Konstruktion % ein: % \begin{macrocode} \begingroup \escapechar=-1 \expandafter\toks@\expandafter{\ser@precode} \edef\@tempa{\the\toks@ \noexpand\global\noexpand\let \csname long\string #1\endcsname \noexpand\undefined \noexpand\global\noexpand\let \csname short\string #1\endcsname \noexpand\undefined} \toks@\expandafter{\@tempa} \xdef\ser@precode{\the\toks@} \endgroup } % \end{macrocode} % |\DeclareBulkmailCommand| darf nur in der Pr"aambel verwendet werden: % \begin{macrocode} \@onlypreamble\DeclareBulkmailCommand % \end{macrocode} % Jetzt k"onnen wir die einzelnen Macros leicht definieren: % \begin{macrocode} \DeclareBulkmailCommand{\familyname} \DeclareBulkmailCommand{\firstname} \DeclareBulkmailCommand{\secondname} \DeclareBulkmailCommand{\nickname} \DeclareBulkmailCommand{\degree} % \end{macrocode} % Eine "ubliche Anwendung sieht demnach so aus: % \begin{verbatim} % \documentclass{letter} % ... % \usepackage{bulkmail} % ... % \SendTo{\female % \familyname{Kunz} % \firstname[Ch.]{Christiane} % \nickname{Chris} % \degree[Prof.]{Prof.~Dr.} % }{\printname\\ % ...} % ... % \beign{document} % \begin{bulkmail} % \opening{\iffemale % Sehr geehrte Frau~\familyname % \fi % \ifmale % Sehr geehrter Herr~\familyname % \fi} % ... % \end{bulkmail} % \end{document} % \end{verbatim} % Und damit der Name auch im Fenster erscheint, noch das Macro % |\printname|. Dieses Macro kann vom Benutzer in der Pr"aambel % geeignet umdefiniert werden. % \begin{macrocode} \newcommand{\printname}{% \ignorespaces \ifx\longfirstname\undefined\else \longfirstname~% \fi \ifx\shortsecondname\undefined\else \shortsecondname~% \fi \longfamilyname } % \end{macrocode} %\iffalse % %\fi % % \iffalse ********************************************* METACOMMENT % Die folgende Section erscheint nicht in der Dokumentation! % ------------------------------------------------------------------ % \Section{Die CharacterTable} % Das hier dient nur dazu, die CharacterTable aus den generierten % Dateien rauszuhalten. % \begin{macrocode} %<*installation> \endinput % % \end{macrocode} % |\endinput| veranla"st |\generateFile| zum Abbruch der % Bearbeitung. % ------------------------------------------------------------------ % Ab jetzt wieder im Ausdruck! % ********************************************** END METACOMMENT \fi % %% \CharacterTable %% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z %% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z %% Digits \0\1\2\3\4\5\6\7\8\9 %% Exclamation \! Double quote \" Hash (number) \# %% Dollar \$ Percent \% Ampersand \& %% Acute accent \' Left paren \( Right paren \) %% Asterisk \* Plus \+ Comma \, %% Minus \- Point \. Solidus \/ %% Colon \: Semicolon \; Less than \< %% Equals \= Greater than \> Question mark \? %% Commercial at \@ Left bracket \[ Backslash \\ %% Right bracket \] Circumflex \^ Underscore \_ %% Grave accent \` Left brace \{ Vertical bar \| %% Right brace \} Tilde \~} %% % \Finale