summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/generic/dcpic
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2009-12-31 01:44:07 +0000
committerKarl Berry <karl@freefriends.org>2009-12-31 01:44:07 +0000
commit35a5ddb9c4a7ab6239bc84741df4cbd8cf8e2ac9 (patch)
treea3f908782043bf1e8a2cd3e385c695589756573e /Master/texmf-dist/tex/generic/dcpic
parentf84374dfd46b282099b639296e3b952f4d52746f (diff)
dcpic update (27dec09)
git-svn-id: svn://tug.org/texlive/trunk@16547 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/generic/dcpic')
-rw-r--r--Master/texmf-dist/tex/generic/dcpic/dcpic.sty1378
1 files changed, 1378 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/generic/dcpic/dcpic.sty b/Master/texmf-dist/tex/generic/dcpic/dcpic.sty
new file mode 100644
index 00000000000..4c1ef123710
--- /dev/null
+++ b/Master/texmf-dist/tex/generic/dcpic/dcpic.sty
@@ -0,0 +1,1378 @@
+%% DC-PiCTeX
+%% Copyright (c) 1990-2009 Pedro Quaresma, Coimbra, Portugal
+%% 11/1990 (version 1.0);
+%% 10/1991 (version 1.1);
+%% 9/1993 (version 1.2);
+%% 3/1995 (version 1.3);
+%% 7/1996 (version 2.1);
+%% 5/2001 (version 3.0);
+%% 11/2001 (version 3.1);
+%% 1/2002 (version 3.2)
+%% 5/2002 (version 4.0);
+%% 3/2003 (version 4.1);
+%% 12/2004 (version 4.1.1)
+%% 3/2007 (version 4.2)
+%% 5/2008 (version 4.2.1)
+%% 8/2008 (version 4.3)
+%% 12/2008 (version 4.3.1)
+%% 12/2009 (version 4.3.2)
+
+\immediate\write10{Package DCpic 2009/12/22 v4.3.2}
+
+\ProvidesPackage{dcpic}[2009/12/22 v4.3.2]
+
+%% Version X.Y.Z
+%% X - major versions
+%% Y - minor versions
+%% Z - bug corrections
+%%
+%% Copyright (c) 1990-2009 Pedro Quaresma <pedro@mat.uc.pt>
+%%
+% This work may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3
+% of this license or (at your option) any later version.
+% The latest version of this license is in
+% http://www.latex-project.org/lppl.txt
+% and version 1.3 or later is part of all distributions of LaTeX
+% version 2005/12/01 or later.
+%
+% This work has the LPPL maintenance status `maintained'.
+%
+% The Current Maintainer of this work is Pedro Quaresma (pedro@mat.uc.pt).
+%
+% This work consists of the files dcpic.sty.
+%%
+%% Coimbra, 22 de Dezembro de 2009 (2009/12/22)
+%% Pedro Quaresma de Almeida
+%%
+%% DCpic is a package of \TeX\ macros for graph modelling in a
+%% (La)\TeX\ or Con\TeX t document. Its distinguishing features are:
+%% the use of \PiCTeX\ a powerful graphical engine, and a simple
+%% specification syntax. A graph is described in terms of its objects
+%% and its edges. The objects are textual elements and the edges can
+%% have various straight or curved forms.
+%%
+%%
+%% A graph in DCpic is a "picture" in \PiCTeX, in which we place our
+%% {\em objects} and {\em morphisms} (edges). The user's commands in
+%% DCpic are: {\tt begindc} and {\tt enddc} which establishe the
+%% coordinate system where the objects will by placed; {\tt obj}, the
+%% command which defines the place and the contents of each object;
+%% {\tt mor}, and {\tt cmor}, the commands which define the
+%% morphisms, linear and curved edges, and its labels.
+%%
+%% Example:
+%% \begindc{\commdiag}[3]
+%% \obj(10,15){$A$}
+%% \obj(25,15){$B$}
+%% \obj(40,15){$C$}
+%% \mor{$A$}{$B$}{$f$}
+%% \mor{$B$}{$C$}{$g$}
+%% \cmor((10,11)(11,7)(15,6)(25,6)(35,6)(39,7)(40,11))
+%% \pup(25,3){$g\circ f$}
+%% \enddc
+%%
+%% NOTES:
+%% all the numeric values should be integer values.
+%%
+%% Available commands:
+%%
+%% The environment:
+%% \begindc{#1}[#2]
+%% #1 - Graph type
+%% 0 = "commdiag" (commutative diagram)
+%% 1 = "digraph" (direct graph)
+%% 2 = "undigraph" (undirect graph)
+%% 3 = "cdigraph" with incircled objects
+%% 4 = "cundigraph" with incircled objects
+%% (optional) #2 - magnification factor (default value, 30)
+%%
+%% \enddc
+%%
+%% Objects:
+%% \obj(#1,#2)[#3]{#4}[#5]
+%% #1 and #2 - coordenates
+%% (optional) #3 - Label, to be used in the morphims command, if not
+%% present the #4 will be used to that purpose
+%% #4 - Object contents
+%% (optional) #5 - placement of the object (default value \north)
+%% 0="\pcent", center
+%% 1="\north", north
+%% 2="\northeast", northeast
+%% 3="\east", east
+%% 4="\southeast", southeast
+%% 5="\south", south
+%% 6="\southwest", southwest
+%% 7="\west", west
+%% 8="\northwest", northwest
+%% !!! Note !!!
+%% if you omit the #3 argument (label) and the #4 argument is a
+%% complex LaTeX command this can cause this command to crash. In
+%% this case you must specify a label (the empty label [], if you do
+%% needed it it for nothing).
+%%
+%% Morphims (linear edges). This commando has to two major variants
+%% i) Starting and Ending objects specification
+%% \mor{#1}{#2}[#5,#6]{#7}[#8,#9]
+%%
+%% As you can see this first form is (intencionaly) badly formed, the
+%% arguments #3 and #4 are missing (the actual command is correctly
+%% formed).
+%%
+%% #1 - The starting object reference
+%% #2 - The ending object reference
+%%
+%% from this two we will obtain the objects coordinates, and also the
+%% dimensions of the enclosing box.
+%%
+%% The objects box dimensions are used to do an automatic adjustment of
+%% the edge width.
+%%
+%% from #1 we obtain (x,y), (#1,#2) in the second form
+%% from #2 we obtain (x',y'), (#3,#4) in the second form
+%%
+%% this values will be passed to the command second form
+%%
+%%ii) Two points coordinates specification
+%% \mor(#1,#2)(#3,#4)[#5,#6]{#7}[#8,#9]
+%%
+%% Now we can describe all the arguments
+%%
+%% #1 and #2 - coordinates (beginning)
+%% #3 and #4 - coordinates (ending)
+%%(optional)#5,#6 - correction factors (defaul values, 10 and 10)
+%% #5 - actual beginning of the edge
+%% #6 - actual ending of the edge
+%% #7 - text (morphism label)
+%%(optional)#8,#9
+%% #8 - label placement
+%% 1 = "\atright", at right, default value
+%% -1 = "\atleft", at left
+%% #9 - edge type
+%% 0 = "\solidarrow", default edge
+%% 1 = "\dashArrow"
+%% 2 = "\solidline"
+%% 3 = "\dashline"
+%% 4 = "\dotline"
+%% 5 = "\injectionarrow" --- old value 3
+%% 6 = "\aplicationarrow" --- old value 4
+%% 7 = "\surjectivearrow" --- old value 5
+%% 8 = "\equalline" (thanks to Ruben Debeerst),
+%% 9 = "\doublearrow"
+%% 10 = "\doubleopposite"
+%% 11 = "nullarrow" (to allow adding labels to existing arrows)
+%%
+%% Notes: the equalline "arrow" does not provide a second label.
+%%
+%% Curved Morphisms (quadratic edges):
+%% \cmor(#1) #2(#3,#4){#5}[#6]
+%% #1 - list of points (odd number)
+%% #2 - tip direction
+%% 0 = "\pup", pointing up
+%% 1 = "\pdown", pointing down
+%% 2 = "\pright", pointing right
+%% 3 = "\pleft", pointing left
+%% #3 and #4 - coordenates of the label
+%% #5 - morphism label
+%%(optional)#6 - edge type
+%% 0 ="\solidarrow", default value
+%% 1 = "\dashArrow"
+%% 2 = "\solidline"
+%%
+%% Notes: insert a space after the command.
+%% the space after the list of points is mandatory
+%%
+%% Exemples:
+%%\documentclass[a4paper,11pt]{article}
+%%\usepackage{dcpic,pictexwd}
+%%
+%%\begin{document}
+%%\begindc[3]
+%%\obj(14,11){$A$}
+%%\obj(39,11){$B$}
+%%\mor(14,12)(39,12){$f$}%[\atright,\solidarrow]
+%%\mor(39,10)(14,10){$g$}%[\atright,\solidarrow]
+%%\cmor((10,10)(6,11)(5,15)(6,19)(10,20)(14,19)(15,15))
+%% \pdown(2,20){$id_A$}
+%%\cmor((40,7)(41,3)(45,2)(49,3)(50,7)(49,11)(45,12))
+%% \pleft(54,3){$id_B$}
+%%\enddc
+%%
+%%\begindc{\commdiag}[3]
+%%\obj(10,15)[A]{$A$}
+%%\obj(40,15)[Aa]{$A$}
+%%\obj(25,15)[B]{$B$}
+%%\mor{A}{B}{$f$}%[\atright,\solidarrow]
+%%\mor{B}{Aa}{$g$}%[\atright,\solidarrow]
+%%\cmor((10,11)(11,7)(15,6)(25,6)(35,6)(39,7)(40,11))
+%% \pup(25,3){$id_A$}
+%%\enddc
+%%
+%%\newcommand{\barraA}{\vrule height2em width0em depth0em}
+%%\newcommand{\barraB}{\vrule height1.6em width0em depth0em}
+%%\begindc{\commdiag}[35]
+%%\obj(1,1)[Gr]{$G$}
+%%\obj(3,1)[Grstar]{$G_{r^*}$}
+%%\obj(5,1)[H]{$H$}
+%%\obj(2,2)[SigmaG]{$\Sigma^G$}
+%%\obj(6,2)[SigmaH]{$\Sigma^H$}
+%%\obj(1,3)[Lm]{$L_m$}
+%%\obj(3,3)[Krm]{$K_{r,m}$}
+%%\obj(5,3)[Rmstar]{$R_{m^*}$}
+%%\obj(1,5)[L]{$L$}
+%%\obj(3,5)[Lr]{$L_r$}
+%%\obj(5,5)[R]{$R$}
+%%\obj(2,6)[SigmaL]{$\Sigma^L$}
+%%\obj(6,6)[SigmaR]{$\Sigma^R$}
+%%\mor{Gr}{SigmaG}{$\lambda^G$}
+%%\mor{Grstar}{Gr}{$i_5$}[\atleft,\aplicationarrow]
+%%\mor{Grstar}{H}{$r^*$}[\atright,\solidarrow]
+%%\mor{H}{SigmaH}{$\lambda^H$}[\atright,\dashArrow]
+%%\mor{SigmaG}{SigmaH}{$\varphi^{r^*}$}[\atright,\solidarrow]
+%%\mor{Lm}{Gr}{$m$}[\atright,\solidarrow]
+%%\mor{Lm}{L}{$i_2$}[\atleft,\aplicationarrow]
+%%\mor{Krm}{Lm}{$i_3\quad$}[\atright,\aplicationarrow]
+%%\mor{Krm}{Rmstar}{$r$}
+%%\mor{Krm}{Lr}{$i_4$}[\atright,\aplicationarrow]
+%%\mor{Krm}{Grstar}{$m$}
+%%\mor{Rmstar}{R}{$i_6$}[\atright,\aplicationarrow]
+%%\mor{Rmstar}{H}{$m^*$}
+%%\mor{L}{SigmaL}{$\lambda^L$}
+%%\mor{Lr}{L}{$i_1\quad$}[\atright,\aplicationarrow]
+%%\mor{Lr}{R}{$r$}
+%%\mor{R}{SigmaR}{$\lambda^R$}[\atright,\solidarrow]
+%%\mor{SigmaL}{SigmaG}{$\varphi^m$}[\atright,\solidarrow]
+%%\mor{SigmaL}{SigmaR}{$\varphi^r$}
+%%\mor{SigmaR}{SigmaH}{$\varphi^{m^*}$}
+%%\enddc
+%%
+%%\end{document}
+%%-----------------//-------------
+%% Modifications (9/1993)
+%% argument "distance" between de tip of the arrow and the objects
+%% became optional; a new option for the "arrows" (option 3)
+%%
+%% 2/3/1995 (version 1.3)
+%% adds "the aplication arrow" (option 4); the distance between
+%% the label and the "arrow" is now a fixed value (10 units).
+%% 15/7/1996 (version 2.1)
+%% The comand "\mor" has a new sintax. The 5th and 6th
+%% parameters are now the distance between the two objects and
+%% the arrow tips. The 7th parameter is the label. The 8th e 9th
+%% parameters (label position and type of arrow) are now optional
+%%
+%% 5/2001 (version 3.0)
+%% Implementation of the comand "\cmor" based on the quadratic
+%% curver comand of PiCTeX
+%%
+%% 11/2001 (version 3.1)
+%% Changes on the tips of the arrow to became more LaTeX style
+%% (after a conversation on EuroTeX 2001).
+%%
+%% 1/2002 (version 3.2)
+%% Modifica{\c c}{\~a}o dos comandos "obj" e "mor" de forma a introduzir
+%% a especifica{\c c}{\~a}o l{\'o}gica dos morfismos, isto {\'e}, passa-se a
+%% dizer qual {\'e} o objecto de partida e/ou o objecto de chegada
+%% em vez de ter de especificar o morfismo em termos de
+%% coordenadas.
+%% Por outro lado o tamanho das setas passa a ser ajustado
+%% automaticamente em rela{\c c}{\~a}o ao tamanho dos objectos.
+%%
+%% 5/2002 (version 4.0)
+%% Modificação dos comandos "begindc" e "obj"
+%% !!! Modificação da sintaxe destes comandos !!!
+%% O comando "begindc" passou a ter um argumento (obrigatório)
+%% que nos permite especificar o tipo de grafo que estamos a
+%% querer especificar:
+%% "commdiag" (0), para diagramas comutativos
+%% "digraph" (1), para grafos orientados
+%% "undigraph" (2), para grafos não orientados
+%% O comando "obj" modificou a sua sintaxe passou a ter um (após
+%% a especificação das coordenadas, um argumento opcional, um
+%% argumento obrigatório, e um argumento opcional. O primeiro
+%% argumento opcional dá-nos a etiqueta que serve como
+%% referência para a especificação dos morfismos, na sua
+%% ausência usa-se o argumento obrigatório para esse efeito, o
+%% argumento obrigatório dá-nos o "conteúdo" do objecto, nos
+%% diagramas comutativos é centrado no ponto dado pelas
+%% coordenadas sendo o argumento seguinte simplesmente ignorado,
+%% nos grafos o "conteúdo" é colocado numa posição a norte, a
+%% noroeste, a este, ..., sendo que a posição concreta é
+%% especificada pelo último dos argumentos deste comando, o
+%% valor por omissão é o "norte".
+%%
+%% 3/2003 (version 4.1)
+%% Responding to a request of Jon Barker <jeb1@soton.ac.uk> I
+%% create a new type of arrow, the surjective arrow.
+%% For now only horizontal and vertical versions, other angles
+%% are poorly rendered.
+%% 12/2004 (version 4.1.1)
+%% New version for the surjective arrows, solve the problems
+%% with the first implementation of this option.
+%% 3/2007 (version 4.2)
+%% Adds the "providespackage" directive that was missing.
+%% Adds dashed lines, and dotted lines.
+%% 5/2008 (version 4.2.1)
+%% Deleting some counters, trying to avoid the problem "running
+%% out of counters", that occurs because of the use of PiCTeX
+%% and DCpic (only two...)
+%% 8/2008 (version 4.3)
+%% Thanks to Ruben Debeerst (debeerst@mathematik.uni-kassel.de),
+%% he added a new arrow "equalline". After that I
+%% decided to add: the doublearrow; the doublearrow with
+%% opposite directions; the null arrow. This last can be used as
+%% a simple form of adding new labels.
+%%12/2008 (version 4.3.1)
+%% The comand \id is internalised (\!id), it should be that way
+%% from the begining because it is not to be used from the
+%% outside.
+%% The comand \dasharrow was changed to \dashArrow to avoid a
+%% clash with the AMS command with the same name.
+%%12/2009 (version 4.3.2)
+%% There is a conflict between dcpic.sty and hyperref in current
+%% texlive-2009 due to the one letter macro \d (thanks Thorsten
+%% S <thorsten.schwander@gmail.com>).
+%% The \d changed to \deuc (Euclidian Distance). The \x and \y
+%% changed to \xO \yO
+%%-----------------//-------------
+
+\catcode`!=11 % ***** THIS MUST NEVER BE OMITTED (See PiCTeX)
+
+\newcount\aux%
+\newcount\auxa%
+\newcount\auxb%
+\newcount\xO%
+\newcount\yO%
+\newcount\xl%
+\newcount\yl%
+\newcount\deuc%
+\newcount\dnm%
+\newcount\xa%
+\newcount\xb%
+\newcount\xmed%
+\newcount\xc%
+\newcount\xd%
+\newcount\xe
+\newcount\xf
+\newcount\ya%
+\newcount\yb%
+\newcount\ymed%
+\newcount\yc%
+\newcount\yd
+\newcount\ye
+\newcount\yf
+%% "global variables"
+\newcount\expansao%
+\newcount\tipografo% version 4.0
+\newcount\distanciaobjmor% version 4.0
+\newcount\tipoarco% version 4.0
+%\newif\ifarredondada% version 4.0 (initial value "false")
+\newif\ifpara%
+%% version 3.2
+\newbox\caixa%
+\newbox\caixaaux%
+\newif\ifnvazia%
+\newif\ifvazia%
+\newif\ifcompara%
+\newif\ifdiferentes%
+\newcount\xaux%
+\newcount\yaux%
+\newcount\guardaauxa%
+\newcount\alt%
+\newcount\larg%
+\newcount\prof%
+%% for the triming
+\newcount\auxqx
+\newcount\auxqy
+\newif\ifajusta%
+\newif\ifajustadist
+\def\objPartida{}%
+\def\objChegada{}%
+\def\objNulo{}%
+
+
+%%
+%% Stack specification
+%%
+
+%%
+%% Emtpy stack
+%%
+\def\!vazia{:}
+
+%%
+%% Is Empty? : Stack -> Bool
+%%
+%% nvazia - True if Not Empy
+%% vazia - True if Empty
+\def\!pilhanvazia#1{\let\arg=#1%
+\if:\arg\ \nvaziafalse\vaziatrue \else \nvaziatrue\vaziafalse\fi}
+
+%%
+%% Push : Elems x Stack -> Stack
+%%
+\def\!coloca#1#2{\edef\pilha{#1.#2}}
+
+%%
+%% Top : Stack -> Elems
+%%
+%% the empty stack is not taken care
+%% the element is "kept" ("guardado")
+\def\!guarda(#1)(#2,#3)(#4,#5,#6){\def\!id{#1}%
+\xaux=#2%
+\yaux=#3%
+\alt=#4%
+\larg=#5%
+\prof=#6%
+}
+
+\def\!topaux#1.#2:{\!guarda#1}
+\def\!topo#1{\expandafter\!topaux#1}
+
+%%
+%% Pop : Stack -> Stack
+%%
+%% the empty stack is not taken care
+\def\!popaux#1.#2:{\def\pilha{#2:}}
+\def\!retira#1{\expandafter\!popaux#1}
+
+%%
+%% Compares words : Word x Word -> Bool
+%%
+%% compara - True if equal
+%% diferentes - True if not equal
+\def\!comparaaux#1#2{\let\argA=#1\let\argB=#2%
+\ifx\argA\argB\comparatrue\diferentesfalse\else\comparafalse\diferentestrue\fi}
+
+\def\!compara#1#2{\!comparaaux{#1}{#2}}
+
+%% Private Macro
+%% Absolute Value)
+%% \absoluto{n}{absn}
+%% input
+%% n - integer
+%% output
+%% absn - |n|
+\def\!absoluto#1#2{\aux=#1%
+ \ifnum \aux > 0
+ #2=\aux
+ \else
+ \multiply \aux by -1
+ #2=\aux
+ \fi}
+
+
+%% Name definitions for edge types and directions
+\def\solidarrow{0}
+\def\dashArrow{1}
+\def\solidline{2}
+\def\dashline{3}
+\def\dotline{4}
+\def\injectionarrow{5}
+\def\aplicationarrow{6}
+\def\surjectivearrow{7}
+\def\equalline{8}
+\def\doublearrow{9}
+\def\doubleopposite{10}
+\def\nullarrow{11}
+
+%% Name definitions for edge label placement
+\def\atright{-1}
+\def\atleft{1}
+%% Tip direction for curved edges
+\def\pup{0}
+\def\pdown{1}
+\def\pright{2}
+\def\pleft{3}
+%% Type of graph
+\def\commdiag{0}
+\def\digraph{1}
+\def\undigraph{2}
+\def\cdigraph{3}
+\def\cundigraph{4}
+%% Positioning of labels in graphs
+\def\pcent{0}
+\def\north{1}
+\def\northeast{2}
+\def\east{3}
+\def\southeast{4}
+\def\south{5}
+\def\southwest{6}
+\def\west{7}
+\def\northwest{8}
+
+
+
+%%Comando Interno
+%% Ajusta a dist{\^a}ncia entre as setas e os objectos em fun{\c c}{\~a}o das
+%% dimens{\~o}es destes {\'u}ltimos
+%% \ajusta{x}{xl}{y}{yl}{d}{Objecto}
+%% entrada
+%% (x,y) e (xl,yl), coordenadas dos pontos de {\'\i}nicio e fim da seta
+%% d, dist{\^a}ncia especificada pelo utilizador ou 10 (valor por
+%% omiss{\~a}o), Objecto d{\'a}-nos a refer{\^e}ncia do objecto ao qual se est{\'a} a
+%% efectuar o ajuste.
+%% sa{\'\i}da
+%% d, dist{\^a}ncia alterada.
+%%
+%% A dist{\^a}ncia alterada {\'e} o maior valor entre 10 e as dimens{\~o}es
+%% apropriadas da caixa que cont{\^e}m o objecto.
+%% Se o utilizador especificar um valor essa especifica{\c c}{\~a}o
+%% n{\~a}o {\'e} alterada.
+%%
+%% Se a seta {\'e} horizontal usa-se o valor da largura
+%% Se a seta {\'e} vertical usa-se:
+%% o valor da altura se a seta est{\'a} no 1o ou 2o quadrante
+%% o valor da profundidade se a seta est{\'a} no 3o ou 4o quadrante
+%% Se a seta {\'e} {\'o}bliqua vai-se escolher o valor conforme:
+%% de 315 a 45 graus usa-se a largura
+%% de 45 a 135 graus usa-se a altura
+%% de 135 a 225 graus usa-se a largura
+%% de 225 a 315 graus usa-se a profundidade
+\def\!ajusta#1#2#3#4#5#6{\aux=#5%
+ \let\auxobj=#6%
+ \ifcase \tipografo % diagramas comutativos
+ \ifnum\number\aux=10
+ \ajustadisttrue % se o valor é o valor por omissão ajusta
+ \else
+ \ajustadistfalse % caso contrário não ajusta
+ \fi
+ \else % grafos (dirigidos, não dirigidos, com molduras)
+ \ajustadistfalse
+% \or % grafos não dirigidos
+% \ajustadistfalse
+% \else % grafos dirigidos com molduras circulares nos objectos
+% \ifnum\number\aux=8
+% \ajustadisttrue % se o valor é o valor por omissão ajusta
+% \else
+% \ajustadistfalse % caso contrário não ajusta
+% \fi
+ \fi
+ \ifajustadist
+% \tiny Vou ajustar %%%
+% \ifnum\number\aux=10% verificar se s{\~a}o os valores por omiss{\~a}o
+ \let\pilhaaux=\pilha%
+ \loop%
+ \!topo{\pilha}%
+ \!retira{\pilha}%
+ \!compara{\!id}{\auxobj}%
+ \ifcompara\nvaziafalse \else\!pilhanvazia\pilha \fi%
+ \ifnvazia%
+ \repeat%
+%% rep{\~o}e os valores na pilha
+ \let\pilha=\pilhaaux%
+ \ifvazia%
+ \ifdiferentes%
+%%
+%% N{\~a}o {\'e} poss{\'\i}vel efectuar o ajuste dado o utilizador n{\~a}o ter
+%% especificado uma etiqueta para o objecto em quest{\~a}o. {\'E} dado o
+%% valor de 10, igual ao valor por omiss{\~a}o.
+%%
+ \larg=1310720% n{\~a}o faz o ajuste
+ \prof=655360%
+ \alt=655360%
+ \fi%
+ \fi%
+ \divide\larg by 131072
+ \divide\prof by 65536
+ \divide\alt by 65536
+ \ifnum\number\yO=\number\yl
+%% Caso 1 -- seta horizontal
+%%
+%% divide-se por 131072 para se obter metade da largura da caixa em
+%% pontos (pt), isto dado que o texto est{\'a} centrado na caixa. Soma-se
+%% mais tr{\^e}s, que constitue um ajuste imp{\'\i}rico.
+ \advance\larg by 3
+ \ifnum\number\larg>\aux
+ #5=\larg
+ \fi
+ \else
+ \ifnum\number\xO=\number\xl
+ \ifnum\number\yl>\number\yO
+%% Caso 2.1 -- seta vertical de cima para baixa
+%%
+ \ifnum\number\alt>\aux
+ #5=\alt
+ \fi
+ \else
+%% Caso 2.2 -- seta vertical de baixo para cima
+%%
+%% divide-se por 65536 para se obter a altura da caixa em pt. O ajuste
+%% de 5 foi obtido imp{\'\i}ricamente
+ \advance\prof by 5
+ \ifnum\number\prof>\aux
+ #5=\prof
+ \fi
+ \fi
+ \else
+%% Caso 3 -- seta obl{\'\i}qua
+%% Caso 3.1 de 315o a 45o; |x-xl|>|y-yl| e
+%% Caso 3.3 de 135o a 225o; |x-xl|>|y-yl|; Largura
+ \auxqx=\xO
+ \advance\auxqx by -\xl
+ \!absoluto{\auxqx}{\auxqx}%
+ \auxqy=\yO
+ \advance\auxqy by -\yl
+ \!absoluto{\auxqy}{\auxqy}%
+ \ifnum\auxqx>\auxqy
+ \ifnum\larg<10
+ \larg=10
+ \fi
+ \advance\larg by 3
+ #5=\larg
+ \else
+%% Caso 3.2 de 45o a 135o; |x-xl|<|y-yl| e y>0; Largura
+ \ifnum\yl>\yO
+ \ifnum\larg<10
+ \larg=10
+ \fi
+ \advance\alt by 6
+ #5=\alt
+ \else
+%% Caso 3.4 de 225o a 315o; |x-xl|<|y-yl| e y<0; Profundidade
+ \advance\prof by 11
+ #5=\prof
+ \fi
+ \fi
+ \fi
+ \fi
+\fi} % o ramo "else" {\'e} omisso
+
+
+%%Comando Interno
+%% C{\'a}lculo da Raiz Quadrada
+%% raiz{n}{m}
+%% entrada
+%% n - natural
+%% sa{\'\i}da
+%% n - natural
+%% m - maior natural contido na raiz quadrada de n
+\def\!raiz#1#2{\auxa=#1%
+ \auxb=1%
+ \loop
+ \aux=\auxb%
+ \advance \aux by 1%
+ \multiply \aux by \aux%
+ \ifnum \aux < \auxa%
+ \advance \auxb by 1%
+ \paratrue%
+ \else\ifnum \aux=\auxa%
+ \advance \auxb by 1%
+ \paratrue%
+ \else\parafalse%
+ \fi
+ \fi
+ \ifpara%
+ \repeat
+#2=\auxb}
+
+%%Private Macro
+%% Find the starting and ending points of the "arrow" and also the
+%% label position (one coordinate at a time)
+%%
+%% ucoord{x1}{x2}{x3}{x4}{x5}{x6}{+|- 1}
+%% Input
+%% x1,x2,x3,x4,x5
+%% Output
+%% x6
+%%
+%% x2 - x1
+%% x6 = x3 +|- ------- x4
+%% x5
+\def\!ucoord#1#2#3#4#5#6#7{\aux=#2%
+ \advance \aux by -#1%
+ \multiply \aux by #4%
+ \divide \aux by #5%
+ \ifnum #7 = -1 \multiply \aux by -1 \fi%
+ \advance \aux by #3%
+#6=\aux}
+
+%%Private Macro
+%% Euclidean distance between two points
+%%
+%% quadrado{n}{m}{l}
+%% Input
+%% n - natural number
+%% m - natural number
+%% Output
+%% l = (n-m)*(n-m)
+\def\!quadrado#1#2#3{\aux=#1%
+ \advance \aux by -#2%
+ \multiply \aux by \aux%
+#3=\aux}
+
+%%Comando Interno
+%% C{\'a}lculo auxiliar para determinar a dist{\^a}ncia entre o nome do
+%% morfismo e a seta.
+%% entrada
+%% (x,y), (x',y') e o nome do morfismo
+%% sa{\'\i}da
+%% dnm - dist{\^a}ncia do nome ao morfismo respectivo devidamente
+%% compensada pelo tamanho do objecto
+%% Observa{\c c}{\~o}es
+%% A compensa{\c c}{\~a}o s{\'o} est{\'a} a ser feita para setas
+%% horizontais e verticais. As obl{\'\i}quas s{\~a}o tratadas de
+%% outra forma.
+%% algoritmo
+%% caixa0 <- nome do morfismo
+%% se x-xl = 0 entao {recta vertical}
+%% aux <- largura da caixa0
+%% dnm <- convers{\~a}o-sp-pt(aux)/2+3
+%% sen{\~a}o {recta n{\~a}o vertical}
+%% se y-yl = 0 entao {recta horizontal}
+%% aux <- altura+profundidade da caixa0
+%% dnm <- convers{\~a}o-sp-pt(aux)/2+3
+%% sen{\~a}o {recta obl{\'\i}qua}
+%% dnm <- 3
+%% fimse
+%% fimse
+%% fimalgoritmo
+\def\!distnomemor#1#2#3#4#5#6{\setbox0=\hbox{#5}%
+ \aux=#1
+ \advance \aux by -#3
+ \ifnum \aux=0
+ \aux=\wd0 \divide \aux by 131072
+ \advance \aux by 3
+ #6=\aux
+ \else
+ \aux=#2
+ \advance \aux by -#4
+ \ifnum \aux=0
+ \aux=\ht0 \advance \aux by \dp0 \divide \aux by 131072
+ \advance \aux by 3
+ #6=\aux%
+ \else
+ #6=3
+ \fi
+ \fi
+}
+
+
+%%
+%% O ambiente "begindc...enddc"
+%%
+\def\begindc#1{\!ifnextchar[{\!begindc{#1}}{\!begindc{#1}[30]}}
+\def\!begindc#1[#2]{\beginpicture
+ \let\pilha=\!vazia
+ \setcoordinatesystem units <1pt,1pt>
+ \expansao=#2
+ \ifcase #1
+ \distanciaobjmor=10
+ \tipoarco=0 % arrow
+ \tipografo=0 % commutative diagram
+ \or
+ \distanciaobjmor=2
+ \tipoarco=0 % arrow
+ \tipografo=1 % directed graph
+ \or
+ \distanciaobjmor=1
+ \tipoarco=2 % line
+ \tipografo=2 % undirected graph
+ \or
+ \distanciaobjmor=8
+ \tipoarco=0 % arrow
+ \tipografo=3 % directed graph
+% \arredondadotrue % objectos com molduras circulares
+ \or
+ \distanciaobjmor=8
+ \tipoarco=2 % line
+ \tipografo=4 % undirected graph
+% \arredondadotrue % objectos com molduras circulares
+ \fi}
+
+\def\enddc{\endpicture}
+
+
+%% Public macro: "mor"
+%%
+%%
+%% Funtion to built the "arrow" between two points
+%%
+%% The points that are uses to built all the elements of the "arrows"
+%% are:
+%%
+%% (xc,yc)
+%% o
+%% |
+%% o------o---------o---------o------o
+%%(x,y) (xa,ya) (xm,ym) (xb,yb)(xl,yl)
+%%
+%% auxa - distance between (x,y) and (xa,ya), 10pt by default
+%% auxb - distance between (xl,yl) and (xb,yb), 10pt by default
+%%
+\def\mor{%
+ \!ifnextchar({\!morxy}{\!morObjA}}
+\def\!morxy(#1,#2){%
+ \!ifnextchar({\!morxyl{#1}{#2}}{\!morObjB{#1}{#2}}}
+\def\!morxyl#1#2(#3,#4){%
+ \!ifnextchar[{\!mora{#1}{#2}{#3}{#4}}{\!mora{#1}{#2}{#3}{#4}[\number\distanciaobjmor,\number\distanciaobjmor]}}%
+\def\!morObjA#1{%
+ \let\pilhaaux=\pilha%
+ \def\objPartida{#1}%
+ \loop%
+ \!topo\pilha%
+ \!retira\pilha%
+ \!compara{\!id}{\objPartida}%
+ \ifcompara \nvaziafalse \else \!pilhanvazia\pilha \fi%
+ \ifnvazia%
+ \repeat%
+ \ifvazia%
+ \ifdiferentes%
+%%
+%% error message and ficticious parameters
+%%
+ Error: Incorrect label specification%
+ \xaux=1%
+ \yaux=1%
+ \fi%
+ \fi%
+ \let\pilha=\pilhaaux%
+ \!ifnextchar({\!morxyl{\number\xaux}{\number\yaux}}{\!morObjB{\number\xaux}{\number\yaux}}}
+\def\!morObjB#1#2#3{%
+ \xO=#1
+ \yO=#2
+ \def\objChegada{#3}%
+ \let\pilhaaux=\pilha%
+ \loop
+ \!topo\pilha %
+ \!retira\pilha%
+ \!compara{\!id}{\objChegada}%
+ \ifcompara \nvaziafalse \else \!pilhanvazia\pilha \fi
+ \ifnvazia
+ \repeat
+ \ifvazia
+ \ifdiferentes%
+%%
+%% error message and ficticious parameters
+%%
+ Error: Incorrect label specification
+ \xaux=\xO%
+ \advance\xaux by \xO%
+ \yaux=\yO%
+ \advance\yaux by \yO%
+ \fi
+ \fi
+ \let\pilha=\pilhaaux
+ \!ifnextchar[{\!mora{\number\xO}{\number\yO}{\number\xaux}{\number\yaux}}{\!mora{\number\xO}{\number\yO}{\number\xaux}{\number\yaux}[\number\distanciaobjmor,\number\distanciaobjmor]}}
+\def\!mora#1#2#3#4[#5,#6]#7{%
+ \!ifnextchar[{\!morb{#1}{#2}{#3}{#4}{#5}{#6}{#7}}{\!morb{#1}{#2}{#3}{#4}{#5}{#6}{#7}[1,\number\tipoarco] }}
+\def\!morb#1#2#3#4#5#6#7[#8,#9]{\xO=#1%
+ \yO=#2%
+ \xl=#3%
+ \yl=#4%
+ \multiply \xO by \expansao%
+ \multiply \yO by \expansao%
+ \multiply \xl by \expansao%
+ \multiply \yl by \expansao%
+%%
+%% Euclidean distance between two points
+%% d = \sqrt((x-xl)^2+(y-yl)^2)
+%%
+ \!quadrado{\number\xO}{\number\xl}{\auxa}%
+ \!quadrado{\number\yO}{\number\yl}{\auxb}%
+ \deuc=\auxa%
+ \advance \deuc by \auxb%
+ \!raiz{\deuc}{\deuc}%
+%%
+%% the point (xa,ya) is at a distance #5 (default value 10) from the
+%% point (x,y)
+%%
+%% como existem dois pontos em considera{\c c}{\~a}o, o ponto de partida e o
+%% ponto de chegada, vai sei necess{\'a}rio recuperar de novo os seus
+%% valores por pesquisa na pilha
+ \auxa=#5
+ \!compara{\objNulo}{\objPartida}%
+ \ifdiferentes% S{\'o} vai fazer o ajuste quando {\'e} necess{\'a}rio
+ \!ajusta{\xO}{\xl}{\yO}{\yl}{\auxa}{\objPartida}%
+ \ajustatrue
+ \def\objPartida{}% re-inicializar o valor do Objecto de Partida
+ \fi
+%% vai guardar o valor de auxa (ap{\'o}s ajuste) para ser usado no caso
+%% dos morfismos de injec{\c c}{\~a}o.
+ \guardaauxa=\auxa
+%%
+ \!ucoord{\number\xO}{\number\xl}{\number\xO}{\auxa}{\number\deuc}{\xa}{1}%
+ \!ucoord{\number\yO}{\number\yl}{\number\yO}{\auxa}{\number\deuc}{\ya}{1}%
+%% auxa vai ter o valor da dist{\^a}ncia entre os objectos menos a
+%% dist{\^a}ncia da seta ao objecto (10 por omiss{\~a}o)
+ \auxa=\deuc%
+%%
+%% the point (xb,yb) is at a distance #6 (default value 10) from the
+%% point (xl,yl)
+%%
+ \auxb=#6
+ \!compara{\objNulo}{\objChegada}%
+ \ifdiferentes% S{\'o} vai fazer o ajuste quando {\'e} necess{\'a}rio
+% Vou ajustar
+ \!ajusta{\xO}{\xl}{\yO}{\yl}{\auxb}{\objChegada}%
+ \def\objChegada{}% re-inicializar o valor do Objecto de Chegada
+ \fi
+ \advance \auxa by -\auxb%
+ \!ucoord{\number\xO}{\number\xl}{\number\xO}{\number\auxa}{\number\deuc}{\xb}{1}%
+ \!ucoord{\number\yO}{\number\yl}{\number\yO}{\number\auxa}{\number\deuc}{\yb}{1}%
+ \xmed=\xa%
+ \advance \xmed by \xb%
+ \divide \xmed by 2
+ \ymed=\ya%
+ \advance \ymed by \yb%
+ \divide \ymed by 2
+%%
+%% find the coordinates of the label position: (xc,yc)
+%%
+%% after this the values of xmed and ymed are no longer important
+%%
+ \!distnomemor{\number\xO}{\number\yO}{\number\xl}{\number\yl}{#7}{\dnm}%
+ \!ucoord{\number\yO}{\number\yl}{\number\xmed}{\number\dnm}{\number\deuc}{\xc}{-#8}%
+ \!ucoord{\number\xO}{\number\xl}{\number\ymed}{\number\dnm}{\number\deuc}{\yc}{#8}%
+%%
+%% draw the "arrow"
+%%
+\ifcase #9 % 0=solid arrow
+ \arrow <4pt> [.2,1.1] from {\xa} {\ya} to {\xb} {\yb}
+\or % 1=dashed arrow
+ \setdashes
+ \arrow <4pt> [.2,1.1] from {\xa} {\ya} to {\xb} {\yb}
+ \setsolid
+\or % 2=solid line
+ \setlinear
+ \plot {\xa} {\ya} {\xb} {\yb} /
+\or % 3=dashed line
+ \setdashes
+ \setlinear
+ \plot {\xa} {\ya} {\xb} {\yb} /
+ \setsolid
+\or % 4=dotted line
+ \setdots
+ \setlinear
+ \plot {\xa} {\ya} {\xb} {\yb} /
+ \setsolid
+\or % 5=injective arrow
+%% C{\'a}lculos auxiliares
+%%
+%% 3 units, the radius for the tail of the arrow
+%%
+%% repor o valor de auxa
+ \auxa=\guardaauxa
+%% dar a compensa{\c c}{\~a}o para o "rabo"
+ \advance \auxa by 3%
+%%
+%% Note: the values of (xa,ya) will be modified, they will be
+%% "pushed" further away from (x,y) in order to acomodate the tail
+%% of the "arrow"
+%%
+%% find the point (xd,yd), the center of a 3pt circle
+%%
+ \!ucoord{\number\xO}{\number\xl}{\number\xO}{\number\auxa}{\number\deuc}{\xa}{1}%
+ \!ucoord{\number\yO}{\number\yl}{\number\yO}{\number\auxa}{\number\deuc}{\ya}{1}%
+ \!ucoord{\number\yO}{\number\yl}{\number\xa}{3}{\number\deuc}{\xd}{-1}%
+ \!ucoord{\number\xO}{\number\xl}{\number\ya}{3}{\number\deuc}{\yd}{1}%
+%% building the "arrow"
+ \arrow <4pt> [.2,1.1] from {\xa} {\ya} to {\xb} {\yb}
+%% and its "tail"
+ \circulararc -180 degrees from {\xa} {\ya} center at {\xd} {\yd}
+\or % 6=maps "arrow" ("|-->")
+ \auxa=3
+%%
+%% Note: the values of xmed and ymed will be modified
+%%
+%% find the two points that defines the tail of the arrow (segment
+%% (xmed,ymed)(xd,yd))
+ \!ucoord{\number\yO}{\number\yl}{\number\xa}{\number\auxa}{\number\deuc}{\xmed}{-1}%
+ \!ucoord{\number\xO}{\number\xl}{\number\ya}{\number\auxa}{\number\deuc}{\ymed}{1}%
+ \!ucoord{\number\yO}{\number\yl}{\number\xa}{\number\auxa}{\number\deuc}{\xd}{1}%
+ \!ucoord{\number\xO}{\number\xl}{\number\ya}{\number\auxa}{\number\deuc}{\yd}{-1}%
+%% building the "arrow"
+ \arrow <4pt> [.2,1.1] from {\xa} {\ya} to {\xb} {\yb}
+%% and its "tail"
+ \setlinear
+ \plot {\xmed} {\ymed} {\xd} {\yd} /
+\or % 7=surjective arrow ("-->>")
+%% building arrow with the first tip
+ \arrow <4pt> [.2,1.1] from {\xa} {\ya} to {\xb} {\yb}
+%% and the second tip
+ \setlinear
+ \arrow <6pt> [0,.72] from {\xa} {\ya} to {\xb} {\yb}
+\or % 8=equalline
+%% by Ruben Debeerst: equal-line
+%%
+%% sets the separation (distance) between the two parallel lines, if
+%% horizontal or vertical 1pt is enough, if not 2pt
+\auxa=2
+\ifnum\number\yO=\number\yl
+\auxa=1
+\fi
+\ifnum\number\xO=\number\xl
+\auxa=1
+\fi
+%% the two parallel lines will be given by (xmed,ymed)(xd,yd), and
+%% (xe,ye)(xf,yf)
+ \!ucoord{\number\yO}{\number\yl}{\number\xa}{\number\auxa}{\number\deuc}{\xmed}{-1}%
+ \!ucoord{\number\xO}{\number\xl}{\number\ya}{\number\auxa}{\number\deuc}{\ymed}{1}%
+ \!ucoord{\number\yO}{\number\yl}{\number\xa}{\number\auxa}{\number\deuc}{\xd}{1}%
+ \!ucoord{\number\xO}{\number\xl}{\number\ya}{\number\auxa}{\number\deuc}{\yd}{-1}%
+
+ \!ucoord{\number\yO}{\number\yl}{\number\xb}{\number\auxa}{\number\deuc}{\xe}{-1}%
+ \!ucoord{\number\xO}{\number\xl}{\number\yb}{\number\auxa}{\number\deuc}{\ye}{1}%
+ \!ucoord{\number\yO}{\number\yl}{\number\xb}{\number\auxa}{\number\deuc}{\xf}{1}%
+ \!ucoord{\number\xO}{\number\xl}{\number\yb}{\number\auxa}{\number\deuc}{\yf}{-1}%
+ \setlinear
+ \plot {\xmed} {\ymed} {\xe} {\ye} /
+ \plot {\xd} {\yd} {\xf} {\yf} /
+\or % 9=double arrow
+%%
+%% sets the separation (distance) between the two parallel lines, if
+%% horizontal or vertical 2pt is enough, if not 3pt. The extra space
+%% is needed because of the arrow tip.
+\auxa=3
+\ifnum\number\yO=\number\yl
+\auxa=2
+\fi
+\ifnum\number\xO=\number\xl
+\auxa=2
+\fi
+%% the two parallel lines will be given by (xmed,ymed)(xd,yd), and
+%% (xe,ye)(xf,yf)
+ \!ucoord{\number\yO}{\number\yl}{\number\xa}{\number\auxa}{\number\deuc}{\xmed}{-1}%
+ \!ucoord{\number\xO}{\number\xl}{\number\ya}{\number\auxa}{\number\deuc}{\ymed}{1}%
+ \!ucoord{\number\yO}{\number\yl}{\number\xa}{\number\auxa}{\number\deuc}{\xd}{1}%
+ \!ucoord{\number\xO}{\number\xl}{\number\ya}{\number\auxa}{\number\deuc}{\yd}{-1}%
+
+ \!ucoord{\number\yO}{\number\yl}{\number\xb}{\number\auxa}{\number\deuc}{\xe}{-1}%
+ \!ucoord{\number\xO}{\number\xl}{\number\yb}{\number\auxa}{\number\deuc}{\ye}{1}%
+ \!ucoord{\number\yO}{\number\yl}{\number\xb}{\number\auxa}{\number\deuc}{\xf}{1}%
+ \!ucoord{\number\xO}{\number\xl}{\number\yb}{\number\auxa}{\number\deuc}{\yf}{-1}%
+ \arrow <4pt> [.2,1.1] from {\xmed} {\ymed} to {\xe} {\ye}
+ \arrow <4pt> [.2,1.1] from {\xd} {\yd} to {\xf} {\yf}
+\or % 10=double arrow, opposite directions
+%%
+%% sets the separation (distance) between the two parallel lines, if
+%% horizontal or vertical 2pt is enough, if not 3pt. The extra space
+%% is needed because of the arrow tip.
+\auxa=3
+\ifnum\number\yO=\number\yl
+\auxa=2
+\fi
+\ifnum\number\xO=\number\xl
+\auxa=2
+\fi
+%% the two parallel lines will be given by (xmed,ymed)(xd,yd), and
+%% (xe,ye)(xf,yf)
+ \!ucoord{\number\yO}{\number\yl}{\number\xa}{\number\auxa}{\number\deuc}{\xmed}{-1}%
+ \!ucoord{\number\xO}{\number\xl}{\number\ya}{\number\auxa}{\number\deuc}{\ymed}{1}%
+ \!ucoord{\number\yO}{\number\yl}{\number\xa}{\number\auxa}{\number\deuc}{\xd}{1}%
+ \!ucoord{\number\xO}{\number\xl}{\number\ya}{\number\auxa}{\number\deuc}{\yd}{-1}%
+
+ \!ucoord{\number\yO}{\number\yl}{\number\xb}{\number\auxa}{\number\deuc}{\xe}{-1}%
+ \!ucoord{\number\xO}{\number\xl}{\number\yb}{\number\auxa}{\number\deuc}{\ye}{1}%
+ \!ucoord{\number\yO}{\number\yl}{\number\xb}{\number\auxa}{\number\deuc}{\xf}{1}%
+ \!ucoord{\number\xO}{\number\xl}{\number\yb}{\number\auxa}{\number\deuc}{\yf}{-1}%
+ \arrow <4pt> [.2,1.1] from {\xmed} {\ymed} to {\xe} {\ye}
+ \arrow <4pt> [.2,1.1] from {\xf} {\yf} to {\xd} {\yd}
+\or % 11=null arrow (no arrow, only a label)
+%%
+%% does not draw the arrow, it allows to put two labels in one "arrow"
+%%
+\fi
+%% The label positioning.
+%% Se os morfismos s{\~a}o horizontais ou verticais constro{\'\i} uma caixa
+%% centrada no ponto pr{\'e}viamente calculado. Se as setas s{\~a}o
+%% obl{\'\i}quas coloca a caixa de forma a n{\~a}o colidir com o morfismo
+%% tendo em aten{\c c}{\~a}o o quadrante assim como a posi{\c c}{\~a}o
+%% relativa do morfismo e do respectivo nome.
+\auxa=\xl
+\advance \auxa by -\xO%
+\ifnum \auxa=0
+ \put {#7} at {\xc} {\yc}
+\else
+ \auxb=\yl
+ \advance \auxb by -\yO%
+ \ifnum \auxb=0 \put {#7} at {\xc} {\yc}
+ \else
+ \ifnum \auxa > 0
+ \ifnum \auxb > 0
+ \ifnum #8=1
+ \put {#7} [rb] at {\xc} {\yc}
+ \else
+ \put {#7} [lt] at {\xc} {\yc}
+ \fi
+ \else
+ \ifnum #8=1
+ \put {#7} [lb] at {\xc} {\yc}
+ \else
+ \put {#7} [rt] at {\xc} {\yc}
+ \fi
+ \fi
+ \else
+ \ifnum \auxb > 0
+ \ifnum #8=1
+ \put {#7} [rt] at {\xc} {\yc}
+ \else
+ \put {#7} [lb] at {\xc} {\yc}
+ \fi
+ \else
+ \ifnum #8=1
+ \put {#7} [lt] at {\xc} {\yc}
+ \else
+ \put {#7} [rb] at {\xc} {\yc}
+ \fi
+ \fi
+ \fi
+ \fi
+\fi
+}
+
+%%
+%% Comando para construir a "seta" curvilinea entre dois objectos
+%%
+%% \cmor(<lista de pontos (n. impar)>){<etiqueta>}
+%%
+%% Em primeiro lugar {\'e} necess{\'a}rio modificar o comando plot de forma a
+%% que a sintaxe de utiliza{\c c}{\~a}o do novo comando seja coerente com a
+%% sintaxe dos restantes comandos
+%%
+\def\modifplot(#1{\!modifqcurve #1}
+\def\!modifqcurve(#1,#2){\xO=#1%
+ \yO=#2%
+ \multiply \xO by \expansao%
+ \multiply \yO by \expansao%
+ \!start (\xO,\yO)
+ \!modifQjoin}
+\def\!modifQjoin(#1,#2)(#3,#4){\xO=#1%
+ \yO=#2%
+ \xl=#3%
+ \yl=#4%
+ \multiply \xO by \expansao%
+ \multiply \yO by \expansao%
+ \multiply \xl by \expansao%
+ \multiply \yl by \expansao%
+ \!qjoin (\xO,\yO) (\xl,\yl) % \!qjoin is defined in QUADRATIC
+ \!ifnextchar){\!fim}{\!modifQjoin}}
+\def\!fim){\ignorespaces}
+
+%%
+%% O comando para desenhar a seta vai receber a lista de pontos da qual
+%% retira o {\'u}ltimo par de pontos, dependente da escolha dada pelo
+%% utilizador a seta vai ser desenhada para cima, para baixo, para a
+%% direita ou para a esquerda
+%%
+\def\setaxy(#1{\!pontosxy #1}
+\def\!pontosxy(#1,#2){%
+ \!maispontosxy}
+\def\!maispontosxy(#1,#2)(#3,#4){%
+ \!ifnextchar){\!fimxy#3,#4}{\!maispontosxy}}
+\def\!fimxy#1,#2){\xO=#1%
+ \yO=#2
+ \multiply \xO by \expansao
+ \multiply \yO by \expansao
+ \xl=\xO%
+ \yl=\yO%
+ \aux=1%
+ \multiply \aux by \auxa%
+ \advance\xl by \aux%
+ \aux=1%
+ \multiply \aux by \auxb%
+ \advance\yl by \aux%
+ \arrow <4pt> [.2,1.1] from {\xO} {\yO} to {\xl} {\yl}}
+
+
+%%
+%% Temos agora a defini{\c c}{\~a}o do comando "cmor"
+%%
+\def\cmor#1 #2(#3,#4)#5{%
+ \!ifnextchar[{\!cmora{#1}{#2}{#3}{#4}{#5}}{\!cmora{#1}{#2}{#3}{#4}{#5}[0] }}
+\def\!cmora#1#2#3#4#5[#6]{%
+ \ifcase #2% para cima "\pup" (pointing up)
+ \auxa=0% x mant{\^e}m-se
+ \auxb=1% o y "sobe"
+ \or% para baixo "\pdown" (pointing down)
+ \auxa=0% x mant{\^e}m-se
+ \auxb=-1% o y "desce"
+ \or% para a direita "\pright" (pointing right)
+ \auxa=1% o x move-se para a direita
+ \auxb=0% o y mant{\^e}m-se
+ \or% para a esquerda "\pleft" (pointing left)
+ \auxa=-1% o x move-se para a esquerda
+ \auxb=0% o y mant{\^e}m-se
+ \fi % constru{\c c}{\~a}o do arco
+ \ifcase #6 % arco (com seta) s{\'o}lido
+ \modifplot#1% Desenhar o arco
+ % constru{\c c}{\~a}o da seta
+ \setaxy#1
+ \or % arco (com seta) a tracejado
+ \setdashes
+ \modifplot#1% Desenhar o arco
+ \setaxy#1
+ \setsolid
+ \or % arco sem seta
+ \modifplot#1% Desenhar o arco
+ \fi % seta de injec{\c c}{\~a}o
+%% coloca{\c c}{\~a}o da etiqueta do morfismo
+ \xO=#3%
+ \yO=#4%
+ \multiply \xO by \expansao%
+ \multiply \yO by \expansao%
+ \put {#5} at {\xO} {\yO}}
+
+%%
+%% Comando para construir os Objectos
+%% \obj(x,y){<texto>}[<etiqueta>]
+%%
+\def\obj(#1,#2){%
+ \!ifnextchar[{\!obja{#1}{#2}}{\!obja{#1}{#2}[Nulo]}}
+\def\!obja#1#2[#3]#4{%
+ \!ifnextchar[{\!objb{#1}{#2}{#3}{#4}}{\!objb{#1}{#2}{#3}{#4}[1]}}
+\def\!objb#1#2#3#4[#5]{%
+ \xO=#1%
+ \yO=#2%
+ \def\!pinta{\normalsize$\bullet$}% para definir o tamanho normal das pintas
+ \def\!nulo{Nulo}%
+ \def\!arg{#3}%
+ \!compara{\!arg}{\!nulo}%
+ \ifcompara\def\!arg{#4}\fi%
+ \multiply \xO by \expansao%
+ \multiply \yO by \expansao%
+ \setbox\caixa=\hbox{#4}%
+ \!coloca{(\!arg)(#1,#2)(\number\ht\caixa,\number\wd\caixa,\number\dp\caixa)}{\pilha}%
+ \auxa=\wd\caixa \divide \auxa by 131072
+ \advance \auxa by 5
+ \auxb=\ht\caixa
+ \advance \auxb by \number\dp\caixa
+ \divide \auxb by 131072
+ \advance \auxb by 5
+%(\number\auxa,
+%\number\auxb)
+% \aux=\ht\caixa \divide \auxa by 131072
+% \advance \auxa by 5
+% \auxb=\dp\caixa \divide \auxb by 131072
+% \advance \auxb by 8
+ \ifcase \tipografo % diagramas comutativos
+ \put{#4} at {\xO} {\yO}
+ \or % grafos dirigidos
+ \ifcase #5 % c=0
+ \put{#4} at {\xO} {\yO}
+ \or % n=1
+ \put{\!pinta} at {\xO} {\yO}
+ \advance \yO by \number\auxb % height+depth+5
+ \put{#4} at {\xO} {\yO}
+ \or % ne=2
+ \put{\!pinta} at {\xO} {\yO}
+ \advance \auxa by -2 % para fazer o ajuste (imperfeito)
+ \advance \auxb by -2 % ao raio da circunferencia de centro (x,y)
+ \advance \xO by \number\auxa % width+5
+ \advance \yO by \number\auxb % height+depth+5
+ \put{#4} at {\xO} {\yO}
+ \or % e=3
+ \put{\!pinta} at {\xO} {\yO}
+ \advance \xO by \number\auxa % width+5
+ \put{#4} at {\xO} {\yO}
+ \or % se=4
+ \put{\!pinta} at {\xO} {\yO}
+ \advance \auxa by -2 % para fazer o ajuste (imperfeito)
+ \advance \auxb by -2 % ao raio da circunferencia de centro (x,y)
+ \advance \xO by \number\auxa % width+5
+ \advance \yO by -\number\auxb % height+depth+5
+ \put{#4} at {\xO} {\yO}
+ \or % s=5
+ \put{\!pinta} at {\xO} {\yO}
+ \advance \yO by -\number\auxb % height+depth+5
+ \put{#4} at {\xO} {\yO}
+ \or % sw=6
+ \put{\!pinta} at {\xO} {\yO}
+ \advance \auxa by -2 % para fazer o ajuste (imperfeito)
+ \advance \auxb by -2 % ao raio da circunferencia de centro (x,y)
+ \advance \xO by -\number\auxa % width+5
+ \advance \yO by -\number\auxb % height+depth+5
+ \put{#4} at {\xO} {\yO}
+ \or % w=7
+ \put{\!pinta} at {\xO} {\yO}
+ \advance \xO by -\number\auxa % width+5
+ \put{#4} at {\xO} {\yO}
+ \or % nw=8
+ \put{\!pinta} at {\xO} {\yO}
+ \advance \auxa by -2 % para fazer o ajuste (imperfeito)
+ \advance \auxb by -2 % ao raio da circunferencia de centro (x,y)
+ \advance \xO by -\number\auxa % width+5
+ \advance \yO by \number\auxb % height+depth+5
+ \put{#4} at {\xO} {\yO}
+ \fi
+ \or % grafos nao dirigidos
+ \ifcase #5 % c=0
+ \put{#4} at {\xO} {\yO}
+ \or % n=1
+ \put{\!pinta} at {\xO} {\yO}
+ \advance \yO by \number\auxb % height+depth+5
+ \put{#4} at {\xO} {\yO}
+ \or % ne=2
+ \put{\!pinta} at {\xO} {\yO}
+ \advance \auxa by -2 % para fazer o ajuste (imperfeito)
+ \advance \auxb by -2 % ao raio da circunferencia de centro (x,y)
+ \advance \xO by \number\auxa % width+5
+ \advance \yO by \number\auxb % height+depth+5
+ \put{#4} at {\xO} {\yO}
+ \or % e=3
+ \put{\!pinta} at {\xO} {\yO}
+ \advance \xO by \number\auxa % width+5
+ \put{#4} at {\xO} {\yO}
+ \or % se=4
+ \put{\!pinta} at {\xO} {\yO}
+ \advance \auxa by -2 % ver acima
+ \advance \auxb by -2
+ \advance \xO by \number\auxa % width+5
+ \advance \yO by -\number\auxb % height+depth+5
+ \put{#4} at {\xO} {\yO}
+ \or % s=5
+ \put{\!pinta} at {\xO} {\yO}
+ \advance \yO by -\number\auxb % height+depth+5
+ \put{#4} at {\xO} {\yO}
+ \or % sw=6
+ \put{\!pinta} at {\xO} {\yO}
+ \advance \auxa by -2 % ver acima
+ \advance \auxb by -2
+ \advance \xO by -\number\auxa % width+5
+ \advance \yO by -\number\auxb % height+depth+5
+ \put{#4} at {\xO} {\yO}
+ \or % w=7
+ \put{\!pinta} at {\xO} {\yO}
+ \advance \xO by -\number\auxa % width+5
+ \put{#4} at {\xO} {\yO}
+ \or % nw=8
+ \put{\!pinta} at {\xO} {\yO}
+ \advance \auxa by -2 % ver acima
+ \advance \auxb by -2
+ \advance \xO by -\number\auxa % width+5
+ \advance \yO by \number\auxb % height+depth+5
+ \put{#4} at {\xO} {\yO}
+ \fi
+% \or % grafos dirigidos com molduras circulares nos objectos
+% \advance \auxa by 4
+% \put{\circle{\auxa}} [Bl] at {\xO} {\yO}
+% \put{#4} at {\xO} {\yO}
+% \or % grafos não dirigidos com molduras circulares nos objectos
+ \else % grafos com molduras circulares nos objectos
+ \ifnum\auxa<\auxb % determina a maior das dimensões
+ \aux=\auxb
+ \else
+ \aux=\auxa
+ \fi
+% se a largura da caixa é menor do que 1em então o tamanho
+% tamanho é ajustado para esse valor mínimo
+ \ifdim\wd\caixa<1em
+ \dimen99 = 1em
+ \aux=\dimen99 \divide \aux by 131072
+ \advance \aux by 5
+ \fi
+ \advance\aux by -2 %folga entre o objecto e a moldura
+ \multiply\aux by 2 %
+ \ifnum\aux<30
+ \put{\circle{\aux}} [Bl] at {\xO} {\yO}
+ \else
+ \multiply\auxa by 2
+ \multiply\auxb by 2
+ \put{\oval(\auxa,\auxb)} [Bl] at {\xO} {\yO}
+ \fi
+ \put{#4} at {\xO} {\yO}
+ \fi
+}
+
+
+\catcode`!=12 % ***** THIS MUST NEVER BE OMITTED (see PiCTeX)