/* Das Programm erlaubt das Erstellen von Zeichnungen */ /* fuer LaTeX. Notwendig ist hierzu latexdraw.sty mit */ /* den darin aufgerufenen sty-Dateien */ /* interner Koordinatenursprung fuer Zeichnung und Menue */ /* links unten am Schirm. */ /* Weiteres in der Beschreibung latexdraw.tex */ /* Stand 09.05.1999, copyright: H.-J. Siegert, TUM */ /* nichtkommerzielle Nutzung F&L Hochschulen erlaubt */ /* gegen Stand v. 19.03.1999 undelete ->UnDelete */ /* gegen Stand v. 23.08.1998 STDIN ueber thread */ /* gegen Stand v. 22.08.1998 Dateiname im Window-Namen */ /* gegen Stand v. 12.04.1998 eigene cmap, wenn noetig */ /* gegen Stand v. 28.10.1997 cast bei wi in rotate */ /* gegen Stand v. 02.08.1997 erweitert fuer read von stdin */ /* gegen Stand v. 17.06.1997 dgrenz Faktor 0.3 statt 0.5 */ /* gegen Stand v. 19.03.1997 groessere Differenz beim */ /* Ausrichten vertikale, horizontale Linien */ /* gegen Stand v. 03.02.1997 kein snap bei fill */ /* neue Abstandsberechnungen */ /* gegen Stand v. 11.01.1997 bei Kuerzung wg Pfeilen wird */ /* nicht mehr TeX-Definition der Winkel verwendet */ /* gegen Stand v. 24.12.1996 alle Elemente gezeichnet bei */ /* blinken, Abstandsmodifikation unterschiedlich bei */ /* Selektion gefuellter und nichtgefuellter Elemente */ /* gegen Stand v. 20.10.1996 Fehler bei Ausgabe Rechteck */ /* gegen Stand v. 17.09.1996 Fehler in Pfeilen bei Boegen */ /* gegen Stand v. 16.09.1996 Abfrage der Attribute m"oglich */ /* gegen Stand v. 17.08.1996 Fehler in LaTeX-Datei bei */ /* Pieslice (Klammer zu viel) */ /* gegen Stand v. 27.07.1996 ^k bei Zeicheneingabe */ /* gegen Stand v. 22.07.1996 ifdef XK_KP_... */ /* autom. Erzeugung LaTeX-Datei ohne Oeffnung Fenster */ /* (Parameter -io beim Aufruf) */ /* gegen Stand v. 16.05.1996 Ausgabe Linien gepunktet, */ /* strichpunktiert neue Form; LdpArc, LdpEllarc und */ /* LdpBezier mit verkuerzten Boegen wegen Pfeilen! */ /* gegen Stand v. 25.12.1995 auch Cursortasten v. Keypad */ /* gegen Stand v. 19.06.1995 Menuefont ist Option */ /* gegen Stand v. 12.06.1995 bessere Pfeilspitzen */ /* gegen Stand v. 02.06.1995 usleep wg. Linux umbenannt */ /* gegen Stand v. 13.05.1995 Fehler in Darstellung Bezier */ /* gegen Stand v. 27.04.1995 weitere Farben, Bezier gefuellt*/ /* Entkopplung Farbnummer und Anordnung Farbe im Menue */ /* autom. Anordnung Farben im Menue */ /* gegen Stand v. 26.04.1995 Fehler bei Texteingabe */ /* gegen Stand v. 15.04.1995 Korrektur Auswahlrechteck cut, */ /* statt ires,fres static, Fehler in trim und connect */ /* bei Verschieben dazwischen */ /* gegen Stand v. 07.04.1995 Korrektur chatt bei Text */ /* gegen Stand v. 05.04.1995 Digitalisiertablett */ /* gegen Stand v. 02.04.1995 auch Anklickpunkt bei connect */ /* gegen Stand v. 22.03.1995 rot, CapProjecting */ /* gegen Stand v. 19.03.1995 Lesen Versionen < 4.0 */ /* gegen Stand v. 02.03.1995 Laenge Text unabhaengig von */ /* der Fensterbreite */ /* gegen Stand v. 26.02.1995 Fehler bei Abbruch Text */ /* korrigiert, Textposition in chatt aufgenommen */ /* gegen Stand v. 31.01.1995 laengerer Eingabestring */ /* gegen Stand v. 29.01.1995 Fehler in selekt. chatt behoben*/ /* gegen Stand v. 04.01.1995 Selektives chatt,Aufruf-Param. */ /* gegen Stand v. 31.12.1994 Grauwerte bei Monochromschirm */ /* gegen Stand v. 30.09.1994 Andere Berechnung Bezier */ /* gegen Stand v. 21.09.1994 Anordnung Menue */ /* gegen Stand v. 17.09.1994 trim fuer Recht-,Drei-,Viereck */ /* gegen Stand v. 12.09.1994 Auswahlrechteck bei newgroup */ /* gegen Stand v. 20.08.1994 andere Blinkzeiten */ /* gegen Stand v. 17.08.1994 connect mit allen Elementen */ /* gegen Stand v. 28.07.1994 Realisierung von Gruppen */ /* gegen Stand v. 24.07.1994 undo bei loeschen d. backspace */ /* blinken ausgewaehlter Elemente bei mcopy mmove */ /* gegen Stand v. 02.07.1994 Ausrichten Punkte in x oder y */ /* gegen Stand v. 18.06.1994 XSetInputFocus und ^a,^e */ /* gegen Stand v. 06.06.1994 fuellen vorhandener Elemente */ /* gegen Stand v. 02.05.1994 neben up auch down */ /* gegen Stand v. 15.04.1994 Gerade mit Pfeilen st"arker */ /* eingekuerzt */ /* gegen Stand v. 08.04.1994 gespeicherte Ausgabeoptionen */ /* und neue Makros aLdPfeil,eLdPfeil und LdpLine */ /* gegen Stand v. 22.3.1994 uralte Versionsnummern mit CV */ /* werden richtig erkannt */ /* gegen Stand v. 18.03.94 Darstellung Text, der editiert */ /* wird, an alter Position vermeiden */ /* gegen Stand v. 11.03.94 Rundung korrigiert */ /* gegen Stand v. 28.01.94 Gitterwerte werden ausgegeben */ /* gegen Stand v. 22.01.94 parallele Linie kippt nicht */ /* gegen Stand v. 20.01.94 Cursortasten bewegen Bild, */ /* gegen Stand v. 27.11.93 Erweiterung extend auf Boegen, */ /* redraw, */ /* gegen Stand v. 01.11.93 Verbesserung minmax-Berechnung */ /* gegen Stand v. 23.9.93 Definition documentstyle moeglich */ /* gegen Stand v. 23.08.1993 Farben neu definiert */ /* gegen Stand v. 10.8.93 bezier Linientyp variabel */ /* gegen Stand v. 3.7.93 gefuellte Segmente */ /* gegen Stand v. 18.5.92 Aenderung bei pbezabstand */ /* gegen Stand v. 20.12.1992 vorwaerts/rueckwaerts Taste 3, */ /* xend, yend fuer umgebendes Rechteck andersartig bestimmt */ /* farbige Zeichnungelemente */ /* email: siegert@informatik.tu-muenchen.dbp.de */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*#include */ /*# include */ #ifdef THREAD #include #endif #ifdef TABLETT #include "digitizer.h" #endif #define Char char /* Characters (not bytes) */ #define Static static /* Private global funcs and vars */ #define Void void #define siintround(a) (long) (a) /* Rundung bei double nach long */ #define boolean long #define cboolean char #define true 1L #define false 0L #define unbekannt -1 #ifdef TABLETT #define window_name "LaTeXdraw (Siegert, TUM, C15.29)Digi" #endif #ifndef TABLETT #define window_name "LaTeXdraw (Siegert, TUM, C15.29)" #endif #define icon_name "latexdraw" #define intfiletext "LaTeXdraw output file:" #define extfiletext "LaTeX output file:" #define zel 5000 /*Anzahl Zeichnungselemente*/ #define zstr 300 /*Anzahl Stringelemente*/ #define maxldicke 20 /*Liniendicke 1..20 vorhanden */ #define xzmax00 552.0 /*Window-Zeichenbereichbreite x*/ #define yzmax00 760.0 ; /*Window-Hoehe, Zeichenbereichhoehe y*/ #define xfont "8x13bold" /* Windowfont Menue, Prompt*/ #define ersatzfont "8x13" /* Ersatz, falls Textfont fehlt*/ #define ztextfonts 19 /* Zahl Fonts fuer Text in Zeichnung */ /* Fonts in inittextfonts definiert */ #define dminein 3.0 /*minimale Laengen bei der Eingabe*/ #define pi 3.141592653 #define einrueck " " /*einruecken in TEX*/ #define kom "," #define blank " " #define verlline 30.0 #define texfaktorv 0.3 /*1 pixel = texfaktor mm, Voreinstellung!*/ #define maxpunkte 1000 #define maxstrl 123 /* maximale Stringlaenge */ #define maxgruppen 500 /* maximale Anzahl Gruppen */ #define zrequw 5 /* Zahl der gleichzeitigen Requestwindows */ #define prxachse " end point x axis?" #define pryachse " end point y axis?" #define pranfwi " beginning of arc?" #define prendwi " end of arc?" #define prendwisektor " end of arc for next sector?" #define prpoint3 " point 3?" #define prpoint4 " point 4?" #define docstylestd "\\documentstyle[latexdraw]{article}" #define docstyle2e "\\documentclass{article}\\input{latexdraw.sty}" #define wg 3600.0 #define wh 1800.0 #define wv 900.0 #define wdv 2700.0 #define initabstand 300000.0 #define maxabstand 10.0 /* Umrechnung Linienstaerke in pts */ #define lw2pt 0.57 /* Definitionen fuer Suchen von ausgewaehlten Elementen */ /* Wird auch in array suchtypok[][] verwendet */ #define alleelem 0 #define nurtrimel 1 #define nurboundel 2 #define nurgerade 3 #define nurmpel 4 #define nurextendel 5 #define nurfillel 6 #define schwarz 0L #define weiss 1L #define maxzahlfarben 100L #define paint 1L #define erase 0L #define maxlenmenfarbe 9L #define maxlenfarbe 20L #define somenspalten 3L #define tastatur_erwartet 1 #define click_erwartet 2 #define phase2 10 #ifndef XK_KP_Left #define XK_KP_Left XK_Left #define XK_KP_Right XK_Right #define XK_KP_Up XK_Up #define XK_KP_Down XK_Down #endif #define tastecursleft1 XK_Left #define tastecursright1 XK_Right #define tastecursup1 XK_Up #define tastecursdown1 XK_Down #define tastecursleft2 XK_KP_Left #define tastecursright2 XK_KP_Right #define tastecursup2 XK_KP_Up #define tastecursdown2 XK_KP_Down #define tastea XK_a #define tasted XK_d #define tastee XK_e #define tastek XK_k #define tasteplus1 XK_plus #define tasteplus2 XK_KP_Add #define tasteminus1 XK_minus #define tasteminus2 XK_KP_Subtract #define tastedelete XK_Delete #define tastebackspace XK_BackSpace #define tastereturn XK_Return #define tastecontroll XK_Control_L #define tastecontrolr XK_Control_R #define tasteundo XK_Undo #define button1 1 #define button2 2 #define button3 3 #define ttext 2 /*elementtypen*/ #define tgerade 3 #define tkreis 5 #define tkreisgef 6 #define tkreisbogen 7 #define tell 8 #define tellgef 9 #define tellbogen 10 #define trechteckgef 11 #define tbezier 12 #define tdreieckgef 13 #define tviereckgef 14 #define tkreissektorgef 15 #define tellsektorgef 16 #define tbeziergef 17 #define mende 1 /*menue_nummern*/ #define mtext 2 #define mgerade 3 #define mkreis 4 #define mell 5 #define mrechteck 6 #define mbezier 7 #define mpolygon 8 #define mspiegeln 9 #define mkopieren 10 #define mbewegen 11 #define mergaenzen 12 #define mausdehnen 13 #define mbrechen 14 #define mloeschen 15 #define meinrasten 16 #define mgefuellt 17 #define mverbunden 17 #define mbogen 18 #define mparallel 19 #define mlot 20 #define mmittelpunkt 21 #define mpfeilanf 22 #define mpfeilende 23 #define mdick 24 #define mgestrichelt 25 #define mgepunktet 26 #define mlschieben 27 #define moschieben 28 #define muschieben 29 #define mrschieben 30 #define mgitter 31 #define mcenter 32 #define mgross 33 #define mklein 34 #define mxytastatur 35 #define msave 36 #define mkopbewmaus 37 #define mredraw 38 #define mltext 39 #define mrtext 40 #define mbtext 41 #define mttext 42 #define mladen 43 #define mfont 44 #define mcut 45 #define mpaste 46 #define mdreieck 47 #define mcolor 48 #define mviereck 49 #define mup 50 #define mchangelineattr 51 #define mdegrees 52 #define mdown 53 #define mfill 54 #define mgroupmode 55 #define mnewgroup 56 #define mungroup 57 #define mshowgroup 58 #define mgroupok 59 #define mconnect 60 #define mconnxy 61 #define mconnyx 62 #define mrot 63 #define mwinkelrot 64 #define mcapprojecting 65 #define mconnpoint 66 #define mqueryattr 67 #define mread 68 #define mreadzeit 69 #define zmenue 69 typedef Char tmenue[zmenue+1][maxstrl+1]; typedef double telr[zel+1]; typedef long teli[zel+1]; typedef cboolean telb[zel+1]; typedef Char tstr[zstr+1][maxstrl+1]; typedef double tpunkte[6]; typedef struct tbezierkoeff { double ax, bx, cx, dx, dreiax, zweibx, ay, by, cy, dy, dreiay, zweiby; } tbezierkoeff; typedef double terg[5]; Static long zelmax; Static double xanf,yanf,xend,yend,xsnap,ysnap,xprompt,yprompt; Static double xlast,ylast; Static int irootx, irooty, iwinx, iwiny, ixzmax,iyzmax; unsigned int keysbuttons; Static double xzmax0,yzmax0,xzmax,yzmax,xgr,xgrf, kaestchenbreite,kaestchenhoehe; Static double curs_x,curs_y; Static double fgradbo, fbograd, texfaktor,version; Static boolean zeichnen; Static double texdashl, texdotg, texinterd, gridw, gridw0, gridx0, gridy0, gridwx1, gridwy1, gridwx2, gridwy2, xmittelzei, ymittelzei; Static long ltype, lwidth, lends; Static Char dateiname[maxstrl+1],texdateiname[maxstrl+1]; Static FILE *datdeskr; Static double xmarker[5], ymarker[5]; Static boolean bmarker[5]; Static Char pr1[maxstrl+1], pr2[maxstrl+1], pr3[maxstrl+1], pr4[maxstrl+1], pr5[maxstrl+1], pr6[maxstrl+1]; Static Char tpr1res[maxstrl+1], tpr2res[maxstrl+1], tpr3res[maxstrl+1], tpr4res[maxstrl+1]; Static Char EinText[maxstrl+1]; Static Char nullstr[maxstrl+1]; Static Char docstyle[maxstrl+1]; Static tmenue menue, pr2menue, pr3menue; Static double xam[zmenue + 1], yam[zmenue + 1], xem[zmenue + 1], yem[zmenue + 1]; Static boolean selmenue[zmenue + 1]; Static long radiogroup[zmenue + 1]; Static double rpxarray[maxpunkte], rpyarray[maxpunkte]; Static long vater[maxgruppen+1], umbenennung[maxgruppen+1]; long grumax; /*Maximalzahl aktueller Gruppen*/ Static cboolean gruppentag[maxgruppen+1]; Static boolean aenderunggruppen; Static teli typ, sequenz, group; Static telb blink, blinkalt; Static telr x1, y1_, x2, y2, xb1, yb1, xb2, yb2, wanf, wend; Static telr elxmin, elxmax, elymin, elymax; Static teli lineende, linedicke, linetype; Static telr laenge1, laenge2, rotwi, crw, srw; Static teli textno; Static tstr texte; Static long blinkend, blinkfarbe; /* blinkfarbe == paint oder erase */ Static long blinkintervallzaehler; struct timeval st_delay; Static long winkelrotate; Static boolean changelende, changelstyle, changelwidth, changecolor; Static boolean changefont, changeposition; Static Char textausrichtung[9][maxstrl+1]; Static double wzeichenhoehe,wzeichenascent,wzeichendescent, wzeichenbreite; Static double textzeichenhoehe[ztextfonts],textzeichenascent[ztextfonts], textzeichenbreite[ztextfonts]; Static Char textfont[ztextfonts][maxstrl+1], textfontmakro[ztextfonts][maxstrl+1], textfontlabel[ztextfonts][maxstrl+1], menuefont[maxstrl+1]; Static long fontnummer, stdfontnummer, folgefont[ztextfonts], prevfont[ztextfonts]; Static long aktldicke; Static double breite, hoehe, nbreite, nhoehe; Static boolean quer0format,querformat,mitvorspann,nmitvorspann,oldunitlength; Static long phase=0;/* fuer mehrere verbundene Aktionen */ Static long phasexyein; Static long erwartet, winerwartet, koordinateneingegeben; Static long texterase; Static long controlan; Static long tposres, export_kmark, export_relsel, import_zelsel; Static long geoeffnet, dragbox; Static XEvent report; Static Char eingabezeile[maxstrl+1]; Static long aktreadzeit, readphase = 0; Static double readdxx,readdyy,readf; #ifdef THREAD Static pthread_t threadID; #ifdef LINUX #define pthread_attr_default NULL #endif #endif Static long threadausel=0, threadaktiv, threadrunning = 0; Static Time requesttime, lasteventtime; Static boolean wartendexport, requestbelegt[zrequw], requestaktiv[zrequw]; Static boolean tablett; /*true falls Digitizer angeschlossen */ Static boolean nur_texausgabe; Static XSelectionEvent selnotify[zrequw]; Static Atom latexdraw_object, latexdraw_text, latexdraw_selection; Static long requestkakt[zrequw]; Static Colormap cmap; Static XColor rgbistdef[maxzahlfarben]; Static char farbname[maxzahlfarben][maxlenfarbe+1]; Static char menfarbname[maxzahlfarben][maxlenmenfarbe+1]; Static long farbposfarbnr[maxzahlfarben],farbnrfarbpos[maxzahlfarben]; Static long aktzahlfarben; Static long aktcolor,letztesgrau,aktposcolor; Static Pixmap graystipple[9]; Static char graybits[10][2] ={{0x04,0x00},{0x04,0x10},{0x12,0x48},{0x52,0x58}, {0x5a,0x52}, {0xad,0xa7},{0xed,0xb7},{0xfb,0xe7},{0xfb,0xef}, {0xff, 0xff}}; /*fuer Grauwerte der Farben */ #define hcolorbits 16 /* Hoehe colorstipple in Pixels */ #define bcolorbits 16 /* Breite colorstipple in Pixels */ Static char colorbits[hcolorbits*bcolorbits/8+1]; Static Pixmap colorstipple[maxzahlfarben]; /*fuer Grauwerte der Farben */ Static boolean nocolors; Static double intensity[maxzahlfarben]; /* Helligkeit */ Static GC gcinverse, gcxor,gcstd, somengctext[ztextfonts], gctext[ztextfonts], gczeichnung; Static Visual *visual; Static char winname[maxstrl+1]; Static border_width=4; Static XSizeHints size_hints; Static XFontStruct *font_info, *text_font_info[ztextfonts]; Static char *display_name = NULL; Static Display *display; Static Cursor busycursor,textcursor,clickcursor; Static long screen; Static Window win, rootwin, childwin; Static XComposeStatus compose; Static KeySym keysym; Static Pixmap pixmap; Static long button1gedrueckt, button2gedrueckt, button3gedrueckt; Static char symstr[maxstrl+1]; /* Feld, das angibt, ob ein Zeichnungselemettyp (1. Parameter) bei */ /* einem bestimmten Suchvorgang (z.B. nurtrimel, 2. Parameter) */ /* beruecksichtigt werden soll. ja = 'y', nein = 'n' */ /* alleelem,nurtrimel,nurboundel,nurgerade,nurmpel,nurextendel,nurfillel */ Static char suchtypok[18][7]={ {'n', 'n', 'n', 'n', 'n', 'n', 'n'}, /*frei*/ {'n', 'n', 'n', 'n', 'n', 'n', 'n'}, /*frei*/ {'y', 'n', 'n', 'n', 'n', 'n', 'n'}, /*ttext*/ {'y', 'y', 'y', 'y', 'y', 'y', 'y'}, /*tgerade*/ {'n', 'n', 'n', 'n', 'n', 'n', 'n'}, /*frei*/ {'y', 'y', 'y', 'n', 'y', 'n', 'y'}, /*tkreis*/ {'y', 'y', 'y', 'n', 'y', 'n', 'n'}, /*tkreisgef*/ {'y', 'y', 'y', 'n', 'y', 'y', 'y'}, /*tkreisbogen*/ {'y', 'y', 'y', 'n', 'y', 'n', 'y'}, /*tell*/ {'y', 'y', 'y', 'n', 'y', 'n', 'n'}, /*tellgef*/ {'y', 'y', 'y', 'n', 'y', 'y', 'y'}, /*tellbogen*/ {'y', 'n', 'y', 'n', 'y', 'n', 'n'}, /*trechteckgef*/ {'y', 'n', 'n', 'n', 'n', 'n', 'y'}, /*tbezier*/ {'y', 'n', 'y', 'n', 'y', 'n', 'n'}, /*tdreieckgef*/ {'y', 'n', 'y', 'n', 'n', 'n', 'n'}, /*tviereckgef*/ {'y', 'y', 'y', 'n', 'y', 'y', 'n'}, /*tkreissektorgef*/ {'y', 'y', 'y', 'n', 'y', 'y', 'n'}, /*tellsektorgef*/ {'y', 'n', 'n', 'n', 'n', 'n', 'n'}, /*tbeziergef*/ }; Static void test(i) { printf("******test#: %ld\n",i); } Static Void konkat(s, s1, s2) Char *s1, *s2, *s; /* Konkatenation von strings s1 und s2 */ { long i,n1,n2; n1 = strlen(s1); n2 = strlen(s2); for(i=0;i<=n1;i++) s[i]=s1[i]; for(i=0;i<=n2;i++) s[n1+i]=s2[i]; } Static double frand() { /* einfacher Zufallszahlengenerator aus 0...1*/ static long seed=314159267; double xx; seed=69069*seed; xx = seed; xx = xx/4294967296.0+0.5; if (xx<0.0) xx = 0.0; if(xx>=1.0) xx = 0.99; return xx; } Static Void strfirst(namestring,anz) Char *namestring; long anz; /* anz=Anzahl Zeichen, die bleiben */ { long ls; ls=strlen(namestring); if (ls==0) return; if (anz >=ls) return; if (anz <0) anz=0; namestring[anz]='\0'; } Static Void strlast(namestring,anz) Char *namestring; long anz; /* anz=Anzahl Zeichen, die wegfallen*/ { long i,ls; ls=strlen(namestring); if (anz>=ls) { strcpy(namestring,nullstr); return; } if (anz<=0) return; for (i=anz;i<=ls;i++){ namestring[i-anz]=namestring[i]; } } Static Void strinsert(c,nstring,pos) Char *c, *nstring; long pos; /* fuege c als pos-tes Zeichen (Index: pos - 1) in nstring ein*/ { long i,n,index; n=strlen(nstring); index=pos-1; if (index > n) index = n; for (i=n;i>=index;i--) nstring[i+1]=nstring[i]; nstring[index] = *c; } Static Void strdelete(nstring,pos) Char *nstring; long pos; /*loesche pos-tes Zeichen (Index: pos - 1) in nstring*/ { long i,n,index; n=strlen(nstring); index=pos-1; for (i=index;i zahlzeichen) ls = zahlzeichen; for (i=0;i0;i--) { /* i>0 wegen Punkt am Anfang */ if (s[i] == '/') return; if (s[i] == '.') { s[i]='\0'; return; } } } Static boolean strvergl(s1,s2) Char *s1,*s2; { long ls,i; if ((ls=strlen(s1))!=strlen(s2)) return false; for (i=0;i max) max = g; if (b > max) max = b; min = r; if (g < min) min = g; if (b < min) min = b; diff = max - min; v = 1.0*max/skalierung; if ((max ==0)||(diff==0)) { /*Grauwerte */ ordnung = 100.0*(1.0-v); if (v==0.0) ordnung = 0L; /* schwarz */ if (v==1.0) ordnung = 1L; /* weiss */ return ordnung; } s = 1.0*diff/max; rdist = 1.0*(max-r)/diff; gdist = 1.0*(max-g)/diff; bdist = 1.0*(max-b)/diff; if (b==max) h = 4.0+gdist-rdist; if (g==max) h = 2.0+rdist-bdist; if (r==max) h = bdist-gdist; h = h/6.0; if (h < 0.0) h += 1.0; ordnung = 4; /* light, hell*/ if ((s>=0.3)&&(v>0.81)) ordnung = 3; /* pale,hell */ if ((s>=0.7)&&(v>0.81)) ordnung = 1; /* gesaettigt, hell */ if (v<=0.81) ordnung = 2; /* dunkle Farben */ ordnung = 1000.0*(ordnung+h); ordnung = 100.0*(ordnung+(1.0-v)); ordnung = 100.0*(ordnung+(1.0-s)); return ordnung; /* Anmerkung: ordnung steht zunaechst in farbposfarbnr[nr] */ } Static Void reihenfolgefarben() {/* Anordnung der Farben gemaess Ordungskriterium in farbposfarbnr[nr]*/ /* farbposfarbnr und farbnrfarbpos besetzen */ long i,j,nr,nrtmp,postmp; for (nr=0;nri;j--) { if (farbposfarbnr[j] < farbposfarbnr[i]) { postmp = farbnrfarbpos[i]; nrtmp = farbposfarbnr[i]; farbnrfarbpos[i] = farbnrfarbpos[j]; farbnrfarbpos[j] = postmp; farbposfarbnr[i] = farbposfarbnr[j]; farbposfarbnr[j] = nrtmp; } } } for (nr=0;nrerror_code,msg,100); protokoll("warning XError: ",msg); return 0; } Static Void readzeitsymbol() { Char sss[10]; sprintf(sss,"d:%lds",aktreadzeit); strcpy(menue[mreadzeit],sss); } Static Void strichsymbol() { Char sss[10]; sprintf(sss,"=%2ld",aktldicke); strcpy(menue[mdick],sss); } Static Void colorsymbol() { Char sss[maxlenmenfarbe+5]; sprintf(sss,"%2ld:%s",aktcolor,menfarbname[aktcolor]); strcpy(menue[mcolor],sss); } Static long tastegedrueckt() { unsigned long mask; mask=KeyPressMask|KeyReleaseMask; if(XCheckWindowEvent(display,win,mask,&report)==true) return 1; else return 0; } Static Void welt_to_bildschirm(xx, yy, xpix, ypix) double xx, yy; long *xpix, *ypix; /* Umrechnung Punkt (xx,yy) in Bildschirmkoordinaten */ { *xpix = siintround(xx); *ypix = siintround(yzmax - yy); } Static Void getweltkoord(xx, yy) double *xx, *yy; /* Punkt in event report in weltkoord umrechnen */ { long ix,iy; #ifdef TABLETT if ( (tablett) && (report.xany.send_event)) translate_x_to_ltd(report.xbutton.x, report.xbutton.y, xx, yy); else #endif { ix=report.xbutton.x; *xx = ix; iy=iyzmax - report.xbutton.y; *yy= iy; } } Static Void getmotionweltkoord(ix, iy, xx, yy) long ix, iy; double *xx, *yy; /* Punkt ix, iy in weltkoord umrechnen */ { *xx = ix; *yy= (iyzmax - iy); } Static long si_iabs(x) long x; /* Absolutwert ganze Zahl */ { if (x < 0) return (-x); else return x; } Static Void rechteckbildschirmkoord(x1,y1,x2,y2,ix,iy,width,height) double x1,y1,x2,y2; long *ix,*iy,*width,*height; /* Bestimmen Bildschirm-Koordinaten Rechteck */ { long ix2,iy2; welt_to_bildschirm(x1,y1,ix,iy); welt_to_bildschirm(x2,y2,&ix2,&iy2); *width= si_iabs(ix2-*ix); *height= si_iabs(iy2-*iy); if (*ix > ix2) *ix=ix2; if (*iy > iy2) *iy=iy2; } Static Void setcolor(display,gc,zcolor) Display *display; GC gc; long zcolor; { XSetBackground(display,gc,rgbistdef[weiss].pixel); if ((zcolor==weiss) || (zcolor==schwarz)) { XSetFillStyle(display,gc,FillSolid); XSetForeground(display,gc,rgbistdef[zcolor].pixel); return; } if ((zcolor >= aktzahlfarben)||(zcolor <0)) { XSetFillStyle(display,gc,FillSolid); XSetForeground(display,gc,rgbistdef[schwarz].pixel); return; } if (zcolor <= letztesgrau) {/* graustufen */ XSetFillStyle(display,gc,FillOpaqueStippled); XSetStipple(display,gc,graystipple[zcolor-2]); XSetForeground(display,gc,rgbistdef[schwarz].pixel); return; } if (nocolors == false) { XSetFillStyle(display,gc,FillSolid); XSetForeground(display,gc,rgbistdef[zcolor].pixel); } else { XSetFillStyle(display,gc,FillOpaqueStippled); XSetStipple(display,gc,colorstipple[zcolor]); XSetForeground(display,gc,rgbistdef[zcolor].pixel); } } Static Void rechteckinverse(x1,y1,x2,y2) double x1,y1,x2,y2; { long ix,iy,width,height; rechteckbildschirmkoord(x1,y1,x2,y2,&ix,&iy,&width,&height); XFillRectangle(display,win,gcinverse,ix,iy,width,height); } Static Void xorrechteck(x1,y1,x2,y2) double x1,y1,x2,y2; { long ix,iy,width,height; rechteckbildschirmkoord(x1,y1,x2,y2,&ix,&iy,&width,&height); if ((width<5) && (height<5)) return; if (width<5) width=1; if (height<5) height=1; if (x1 < xgr) return; if (x2 < xgr) return; XDrawRectangle(display,win,gcinverse,ix,iy,width,height); } Static Void menuerechteck(x1,y1,x2,y2) double x1,y1,x2,y2; { long ix,iy,width,height; rechteckbildschirmkoord(x1,y1,x2,y2,&ix,&iy,&width,&height); setcolor(display,gcstd,schwarz); XDrawRectangle(display,win,gcstd,ix,iy,width,height); } Static Void setvalues(display,gc,zcolor,line_type,lwidth,lende) Display *display; GC gc; long zcolor,line_type,lwidth,lende; {long line_style,cap_style,lw; double grunddash, grunddot; long dashlist_length; char dashlist[10]; lw = 0.7*lwidth; grunddash = 1.6*lw; if (grunddash <= 3.0) grunddash = 4.0; grunddot = lw; if (grunddot <= 3.0) grunddot = 2.0; else grunddot = 1.0; if (lende == 4) cap_style = CapProjecting; else cap_style = CapButt; if (line_type < 2) line_style=LineSolid; else { if (lw > 3) cap_style = CapRound; else cap_style = CapButt; line_style=LineOnOffDash; dashlist_length = 2; switch (line_type) { case 3: /* gepunktet */ dashlist_length = 2; dashlist[0]=grunddot; dashlist[1]=grunddash; break; case 5: /* gestrichelt */ dashlist_length = 2; dashlist[0]=2.0*grunddash; dashlist[1]=grunddash; break; case 6: /* Textlinie */ dashlist_length = 6; dashlist[0]=4; dashlist[1]=3; dashlist[2]=2; dashlist[3]=2; dashlist[4]=2; dashlist[5]=3; break; case 7: /* strichpunktiert */ dashlist_length = 4; dashlist[0]=2.0*grunddash; dashlist[1]=grunddash; dashlist[2]=grunddot; dashlist[3]=grunddash; break; default: /*nicht definierte Faelle */ dashlist_length = 6; dashlist[0]=2; dashlist[1]=2; dashlist[2]=2; dashlist[3]=2; dashlist[4]=2; dashlist[5]=5; } XSetDashes(display,gc,0,dashlist,dashlist_length); } XSetLineAttributes(display,gc,lw,line_style,cap_style,JoinBevel); setcolor(display,gc,zcolor); } Static Void ausfillpolygon(anzp,zcolor) long anzp,zcolor; { long ix,iy,k; double xx,yy; XPoint points[maxpunkte]; for (k=0;kfont=text_font_info[i]->fid; hilf=text_font_info[i]->ascent; textzeichenascent[i]=hilf; hilf=text_font_info[i]->descent; textzeichenhoehe[i]=hilf + textzeichenascent[i]; hilf=XTextWidth(text_font_info[i],"x",1); textzeichenbreite[i]=hilf; values->line_width=0; values->line_style=LineSolid; somengctext[i] = XCreateGC(display,win,valuemask,values); gctext[i] = XCreateGC(display,win,valuemask,values); } } Static Void init_window_font(display) Display *display; { long hilf,ls,lsmax; char fontname[maxstrl+1]; strcpy(fontname,menuefont); if ((font_info = XLoadQueryFont(display,fontname)) == NULL) {protokoll("can't load font: ", fontname); fehler(7);} hilf=font_info->ascent; wzeichenascent=hilf; hilf=font_info->descent; wzeichendescent = hilf; wzeichenhoehe=wzeichendescent + wzeichenascent; hilf=XTextWidth(font_info,"x",1); wzeichenbreite=hilf; lsmax=0; for (hilf=1;hilf<=zmenue;hilf++) { ls=strlen(menue[hilf]); if (ls>lsmax) lsmax=ls; } for (hilf=0;hilflsmax) lsmax=ls; } kaestchenbreite = lsmax; kaestchenbreite = (kaestchenbreite+3.0)*wzeichenbreite; kaestchenhoehe=1.2*wzeichenhoehe; xgrf= somenspalten*kaestchenhoehe+1.0*wzeichenbreite; xgr=xgrf+kaestchenbreite +3.0*wzeichenbreite; xzmax=xzmax0+xgr; yzmax=yzmax0; if (quer0format==true){ xzmax=yzmax0+xgr; yzmax=xzmax0+1.5*wzeichenhoehe; } xprompt=wzeichenbreite; yprompt=0.5*wzeichenhoehe; ixzmax=(long)floor(xzmax); iyzmax=(long)floor(yzmax); } Static Void initGC(screen, display, win) long screen; Display *display; Window win; /* Erzeugen aller gc und des Fonts */ { unsigned long valuemask = 0; XGCValues values; char fontname[maxstrl+1]; strcpy(fontname,menuefont); valuemask=(GCForeground|GCBackground|GCFunction|GCLineWidth| GCLineStyle|GCCapStyle|GCJoinStyle|GCFillStyle|GCFillRule| GCFont|GCDashOffset|GCDashList|GCArcMode); values.function=GXcopy; values.cap_style=CapButt; values.join_style=JoinBevel; values.fill_style=FillSolid; values.fill_rule=WindingRule; values.arc_mode=ArcPieSlice; values.dash_offset=0; values.dashes=4; if ((font_info = XLoadQueryFont(display,fontname)) == NULL) {protokoll("can't load font: ", fontname); fehler(7);} values.font=font_info->fid; values.line_width=2; values.line_style=LineSolid; values.foreground=BlackPixel(display,screen); values.background=WhitePixel(display,screen); gcinverse = XCreateGC(display,win,valuemask,&values); XSetFunction(display,gcinverse,GXinvert); XSetPlaneMask(display,gcinverse, BlackPixel(display,screen)^WhitePixel(display,screen)); gcxor = XCreateGC(display,win,valuemask,&values); XSetFunction(display,gcxor,GXxor); XSetPlaneMask(display,gcxor, BlackPixel(display,screen)^WhitePixel(display,screen)); values.line_width=1; gcstd = XCreateGC(display,win,valuemask,&values); gczeichnung= XCreateGC(display,win,valuemask,&values); initgctext(display, win,valuemask,&values); } Static Void systemstipple(display,win,nr,intensitaet) Display *display; Window win; long nr; double intensitaet; { /* erzeugen systematisches Stipple fuer Farben bei Monochrom */ long i, bitnr, j, k, helligkeit, maxbits, maxbytes, offset; double faktor; maxbits = hcolorbits*bcolorbits; maxbytes = maxbits/8; if (maxbits > 8*maxbytes) maxbytes++; helligkeit = maxbits*intensitaet; if ((helligkeit % 2)==0) helligkeit++; /* damit keine | _ Linien */ offset = helligkeit % 8; faktor = (double)maxbits/(double)helligkeit; for (i=0;i0.95) /* etwas Zufall ! */ bitnr++; j = bitnr/8; j = j % maxbytes; k = bitnr % 8; colorbits[j] = colorbits[j] & (~ (1<=2)&& (rgbistdef[nr].red ==rgbistdef[weiss].red)&& (rgbistdef[nr].green==rgbistdef[weiss].green)&& (rgbistdef[nr].blue ==rgbistdef[weiss].blue))){ rgbistdef[nr].pixel=rgbistdef[schwarz].pixel; rgbistdef[nr].red=rgbistdef[schwarz].red; rgbistdef[nr].green=rgbistdef[schwarz].green; rgbistdef[nr].blue=rgbistdef[schwarz].blue; rgbistdef[nr].flags=rgbistdef[schwarz].flags; } /* Helligkeit 0..1 bestimmen */ intensity[nr] = (0.299*rgbsolldef.red + 0.587*rgbsolldef.green + 0.114*rgbsolldef.blue)/65535.0; if (nr <= letztesgrau) farbposfarbnr[nr]=nr; else farbposfarbnr[nr]=rgb2hsv2ordnung(rgbsolldef.red, rgbsolldef.green,rgbsolldef.blue,65535); if (nocolors == true) { systemstipple(display, win, nr,intensity[nr]); } } if (nvh != 0) { printf("we try to allocate own colormap\n"); nvh = XGetWindowAttributes(display,win,&winattr); if (nvh != 0) { cmap = XCreateColormap(display,win,winattr.visual,AllocNone); XSetWindowColormap(display,win,cmap); for (nr=0;nr=2)&& (rgbistdef[nr].red ==rgbistdef[weiss].red)&& (rgbistdef[nr].green==rgbistdef[weiss].green)&& (rgbistdef[nr].blue ==rgbistdef[weiss].blue))){ rgbistdef[nr].pixel=rgbistdef[schwarz].pixel; rgbistdef[nr].red=rgbistdef[schwarz].red; rgbistdef[nr].green=rgbistdef[schwarz].green; rgbistdef[nr].blue=rgbistdef[schwarz].blue; rgbistdef[nr].flags=rgbistdef[schwarz].flags; } /* Helligkeit 0..1 bestimmen */ intensity[nr] = (0.299*rgbsolldef.red + 0.587*rgbsolldef.green + 0.114*rgbsolldef.blue)/65535.0; if (nr <= letztesgrau) farbposfarbnr[nr]=nr; else farbposfarbnr[nr]=rgb2hsv2ordnung(rgbsolldef.red, rgbsolldef.green,rgbsolldef.blue,65535); if (nocolors == true) { systemstipple(display, win, nr,intensity[nr]); } } } } for (i=0;i <= 8;i++) { /* Bitmaps fuer grau erzeugen */ graystipple[i]=XCreateBitmapFromData(display,win,graybits[i],4,4); } } Static Void eintragefarbname(nr, colorname) long *nr; Char *colorname; /* Eintragen eines Farbnamens */ /* nr ist Farbnummer, die auch in Farbmakros verwendet wird */ { long i, m; Char cc; if (*nr >= maxzahlfarben) return; /*ignorieren, zu viele Farben*/ strcpy(farbname[*nr],colorname); m=strlen(colorname); /* verkuerzten Farbnamen fuer Menue erzeugen */ if (m<=maxlenmenfarbe) strcpy(menfarbname[*nr],colorname); else { for (i=0; i='0')&&(cc<='9')) menfarbname[*nr][maxlenmenfarbe-1]=cc; menfarbname[*nr][maxlenmenfarbe]='\0'; } *nr = *nr+1; } Static Void initfarbnamen() /* Erzeugen aller verfuegbaren Farbnamen */ /* Reihenfolge der Aufrufe bestimmt Farbnummer in Latex */ /* deshalb darf Reihenfolge nicht mehr ver"andert werden !!! */ /* die Positionsnummer im Farbmenue wird spaeter berechnet */ { long nr; nr=0; eintragefarbname(&nr, "black"); eintragefarbname(&nr, "white"); eintragefarbname(&nr, "gray90"); eintragefarbname(&nr, "gray80"); eintragefarbname(&nr, "gray70"); eintragefarbname(&nr, "gray60"); eintragefarbname(&nr, "gray50"); eintragefarbname(&nr, "gray40"); eintragefarbname(&nr, "gray30"); eintragefarbname(&nr, "gray20"); eintragefarbname(&nr, "gray10"); letztesgrau = nr-1; /*maximal 10*/ if (letztesgrau > 10) {letztesgrau = 10; nr=11;} eintragefarbname(&nr, "red1"); eintragefarbname(&nr, "orange1"); eintragefarbname(&nr, "sienna1"); eintragefarbname(&nr, "gold1"); eintragefarbname(&nr, "yellow"); eintragefarbname(&nr, "chartreuse1"); eintragefarbname(&nr, "green"); eintragefarbname(&nr, "SpringGreen1"); eintragefarbname(&nr, "cyan"); eintragefarbname(&nr, "blue"); eintragefarbname(&nr, "DarkOrchid1"); eintragefarbname(&nr, "orchid1"); eintragefarbname(&nr, "magenta"); eintragefarbname(&nr, "red3"); eintragefarbname(&nr, "orange3"); eintragefarbname(&nr, "brown2"); eintragefarbname(&nr, "orange2"); eintragefarbname(&nr, "yellow3"); eintragefarbname(&nr, "chartreuse3"); eintragefarbname(&nr, "green3"); eintragefarbname(&nr, "SpringGreen3"); eintragefarbname(&nr, "cyan3"); eintragefarbname(&nr, "blue3"); eintragefarbname(&nr, "DarkOrchid3"); eintragefarbname(&nr, "orchid3"); eintragefarbname(&nr, "magenta3"); eintragefarbname(&nr, "MistyRose1"); eintragefarbname(&nr, "PeachPuff1"); eintragefarbname(&nr, "RosyBrown1"); eintragefarbname(&nr, "khaki1"); eintragefarbname(&nr, "LightYellow1"); eintragefarbname(&nr, "wheat1"); eintragefarbname(&nr, "MintCream"); eintragefarbname(&nr, "PaleGreen1"); eintragefarbname(&nr, "LightCyan1"); eintragefarbname(&nr, "LightBlue1"); eintragefarbname(&nr, "thistle1"); eintragefarbname(&nr, "plum1"); eintragefarbname(&nr, "LavenderBlush1"); eintragefarbname(&nr, "PaleTurquoise1"); eintragefarbname(&nr, "DarkSeaGreen1"); eintragefarbname(&nr, "aquamarine1"); eintragefarbname(&nr, "DeepSkyBlue1"); eintragefarbname(&nr, "SlateBlue1"); eintragefarbname(&nr, "MediumOrchid1"); eintragefarbname(&nr, "IndianRed1"); eintragefarbname(&nr, "DeepPink1"); eintragefarbname(&nr, "brown1"); if (nr > maxzahlfarben) aktzahlfarben=maxzahlfarben; else aktzahlfarben = nr; } Static Void schluss(i) long i; { XCloseDisplay(display); if (datdeskr != NULL) fclose(datdeskr); exit(i); } Static double si_fabs(x) double x; /* Absolutwert GP-Zahl */ { if (x < 0.0) return (-x); else return (x); } Static double sisqrt(term, x) double term, x; /* Wurzel mit Ausgleich Rundungsfehler */ /* Wurzel aus neg. Zahl gibt neg. Wert */ { if (x > 0.0) return sqrt(x); else if (si_fabs(x) <= si_fabs(term) * 0.001) return 0.0; else return (-sqrt(si_fabs(x))); } Static double sifsqrt(term, x) double term, x; /* Wurzel mit Ausgleich Rundungsfehler */ /* Wurzel aus neg. Zahl gibt Fehler */ { double w; w = sisqrt(term, x); if (w < 0.0) fehler(5L); return w; } Static double fsign(x) double x; /* Vorzeichen einer GP-Zahl */ { if (x >= 0.0) return 1.0; else return -1.0; } Static Void glersterord(a, b, anz, erg) double a, b; long *anz; double *erg; /* Gl. ax+b=0 loesen */ /* Anzahl anz der Loesungen in erg[1],... */ { *anz = 0; if (a != 0.0) { *anz = 1; erg[1] = -(b / a); } } Static Void glzweiterord(a, b, c, anz, erg) double a, b, c; long *anz; double *erg; /* Gl. ax*x+b*x+c=0 loesen */ /* Anzahl anz der Loesungen in erg[1],... */ { double w, n; if (a == 0.0) { glersterord(b, c, anz, erg); return; } w = b * b - 4.0 * a * c; n = 1.0 / (2.0 * a); w = sisqrt(b * b, w); if (w < 0.0) *anz = 0; if (w == 0.0) { *anz = 1; erg[1] = -b * n; } if (w <= 0.0) return; *anz = 2; erg[1] = (w - b) * n; erg[2] = (-b - w) * n; } Static double drittewurzel(x) double x; { return (-fsign(x) * exp(log(si_fabs(x)) / 3.0)); } Static double Cosh(x) double x; { return ((exp(x) + exp(-x)) / 2.0); } Static double Sinh(x) double x; { return ((exp(x) - exp(-x)) / 2.0); } Static double arcosh(x) double x; { /* x ist groesser 1 !*/ return log(x + sifsqrt(1.0, x * x - 1.0)); } Static double arsinh(x) double x; { return log(x + sifsqrt(1.0, x * x + 1.0)); } Static Void nachkorr(a, b, c, d, e, x) double a, b, c, d, e, *x; /* Nachkorrektur einer Loesung x einer Gleichung */ /* a*x*x*x*x+b*x*x*x+c*x*x+d*x+e=0 */ /* durch Newton-Extrapolation */ { double g, gstr, gzwstr, dx; dx = 0.0; g = (((a * *x + b) * *x + c) * *x + d) * *x + e; gstr = ((4.0 * a * *x + 3.0 * b) * *x + 2.0 * c) * *x + d; if (0.1 * si_fabs(*x * gstr) > si_fabs(g)) /*Korrektur sinnvoll*/ dx = -(g / gstr); else { /*Doppelnullstelle */ gzwstr = (2.0 * a * *x + b) * 6.0 * *x + 2.0 * c; if (0.1 * si_fabs(*x * gzwstr) > si_fabs(gstr)) dx = -(gstr / gzwstr); } *x += dx; } Static Void gldritterord(a, b, c, d, anz, erg) double a, b, c, d; long *anz; double *erg; /* Gl. ax*x*x+b*x*x+c*x+d=0 loesen */ /* Anzahl anz der Loesungen in erg[1],... */ { double p, q, eda, det, r, cphi, sphi, phi, korr; long i; if (a == 0.0) { glzweiterord(b, c, d, anz, erg); goto _L1; } if (si_fabs(d) < 0.001) { glzweiterord(a, b, c, anz, erg); (*anz)++; erg[*anz] = 0.0; goto _L1; } eda = 1 / a; korr = b * eda / -3.0; p = (3.0 * a * c - b * b) * eda * eda / 9.0; q = ((b * b * b * eda / 27.0 - b * c / 6.0) * eda + d / 2.0) * eda; det = q * q + p * p * p; r = fsign(q) * sifsqrt(1.0, si_fabs(p)); if (p == 0.0 && q == 0.0) { *anz = 1; erg[1] = korr; goto _L1; } if (p == 0.0) { *anz = 1; erg[1] = drittewurzel(-2.0 * q) + korr; goto _L1; } if (p < 0.0 && det <= 0.0) { cphi = q / (r * r * r); if (cphi == 0.0) phi = pi / 2.0; else { sphi = sifsqrt(1.0, 1.0 - cphi * cphi); phi = atan(sphi / cphi); } *anz = 3; erg[1] = korr - 2.0 * r * cos(phi / 3.0); erg[2] = 2.0 * r * cos((pi - phi) / 3.0) + korr; erg[3] = 2.0 * r * cos((pi + phi) / 3.0) + korr; goto _L1; } if (p < 0.0 && det > 0.0) { *anz = 1; erg[1] = korr - 2.0 * r * Cosh(arcosh(q / (r * r * r)) / 3.0); goto _L1; } *anz = 1; erg[1] = korr - 2.0 * r * Sinh(arsinh(q / (r * r * r)) / 3.0); _L1: for (i = 1; i <= *anz; i++) nachkorr(0.0, a, b, c, d, &erg[i]); } Static Void glvierterord(a, b, c, d, e, anz, erg) double a, b, c, d, e; long *anz; double *erg; /* Gl. a*x*x*x*x+b*x*x*x+c*x*x+d*x+e=0 loesen */ /* Anzahl anz der Loesungen in erg[1],... */ { double ga, eda, b1, c1, d1, e1, y, w; terg erg1; long anz1, i; if (a == 0.0) { gldritterord(b, c, d, e, anz, erg); goto _L1; } if (si_fabs(e) < 0.001) { gldritterord(a, b, c, d, anz, erg); (*anz)++; erg[*anz] = 0.0; goto _L1; } if (b == 0.0 && d == 0.0) { glzweiterord(a, c, e, &anz1, erg1); *anz = 0; for (i = 1; i <= anz1; i++) { w = sisqrt(1.0, erg1[i]); if (w >= 0.0) { *anz += 2; erg[*anz - 1] = w; erg[*anz] = -w; } } goto _L1; } eda = 1 / a; b1 = b * eda; c1 = c * eda; d1 = d * eda; e1 = e * eda; gldritterord(8.0, -4.0 * c1, 2.0 * b1 * d1 - 8.0 * e1, e1 * (4.0 * c1 - b1 * b1) - d1 * d1, anz, erg); y = erg[1]; ga = 8.0 * y + b1 * b1 - 4.0 * c1; if (si_fabs(8.0 * y) > si_fabs(b1 * b1)) w = 8.0 * y; else w = b1 * b1; if (si_fabs(w) < si_fabs(4.0 * c1)) w = 4.0 * c1; ga = sisqrt(w, ga); *anz = 0; if (ga < 0.0) goto _L1; eda = b1 * y - d1; if (ga == 0.0 && si_fabs(eda) > 0.001) goto _L1; if (ga == 0.0 && si_fabs(eda) <= 0.001) eda = 0.0; else eda /= ga; glzweiterord(1.0, (b1 + ga) / 2.0, y + eda, &anz1, erg1); glzweiterord(1.0, (b1 - ga) / 2.0, y - eda, anz, erg); for (i = 1; i <= anz1; i++) erg[*anz + i] = erg1[i]; *anz += anz1; _L1: for (i = 1; i <= *anz; i++) nachkorr(a, b, c, d, e, &erg[i]); } Static Void initgrid() { gridw0 = 5.0 / texfaktorv; gridw = gridw0; gridx0 = xmittelzei; gridy0 = ymittelzei; gridwx1 = 1.0; gridwy1 = 0.0; gridwx2 = 0.0; gridwy2 = 1.0; } Static Void ftausch(x, y) double *x, *y; { double c; c = *x; *x = *y; *y = c; } Static Void initgruppentag(tag) long tag; { long i; for (i=0; i<=grumax; i++) gruppentag[i] = tag; } Static long sohn(i, gruppe) long gruppe, i; { /*i. Sohn der Gruppe im Baum */ /* Null falls keiner vorhanden */ long j, k; if ((gruppe < 1)||(gruppe >grumax)) return 0; k = 0; for (j=1;j<=grumax;j++) { if (vater[j]==gruppe) { k++; if (k==i) return j; } } return 0; } Static long gruppenwurzel(elsel) long elsel; { /* oberste Gruppe, zu der die angegebene Gruppe gehoert */ /* Null es gibt keine */ long i, gruppe; gruppe = group[elsel]; if ((gruppe < 1)||(gruppe >grumax)) return 0; i = gruppe; while (vater[i] != 0) i = vater[i]; return i; } Static Void markteilbaum(gruppe,tag) long gruppe,tag; { long j,g; j = 1; while ( (g=sohn(j,gruppe)) != 0) {/* j. Sohn von gruppe untersuchen */ j++; markteilbaum(g,tag); } gruppentag[gruppe] = tag; } Static Void blinkgruppe(elsel) long elsel; {/* bei allen Elementen, die zur Gruppe des angegebenen Elements und */ /* den darueberliegenden Gruppen gehoeren wird blink gesetzt */ /* blink wird vorher nicht geloescht ! */ long i,gw; if ((elsel<1)||(typ[elsel]<=0)||(elsel >zelmax)) return; blink[elsel]=true; gw=gruppenwurzel(elsel); if (gw==0) return; markteilbaum(gw,true); for (i=1;i<=zelmax;i++) { if ((typ[i] >0) && (group[i] != 0) && (gruppentag[group[i]] == true)) { /* Element gehoert zu der Gruppe */ blink[i]=true; } } /* alle Elemente der Gruppe sind markiert */ } Static long freiegruppe() { long i; for (i=1;i<=maxgruppen;i++) if (vater[i]==-1){/*freies Element*/ vater[i]=0; gruppentag[i] = false; if (i>grumax) grumax = i; return i; } fehler(17); } Static Void gruppieren(elsel,wurzel) long elsel, wurzel; { /* neue Gruppe bilden */ long g; g = gruppenwurzel(elsel); if (g==wurzel) return; if (g==0) /* Element direkt in Gruppe */ group[elsel] = wurzel; else vater[g]=wurzel; } Static Void grumaxbestimmen() { long i; for (i=grumax;i>0;i--) { if (vater[i] != -1) break; } grumax = i; } Static Void loeschegruppe(elsel) long elsel; { long i, vorh, wurzel; vorh=false; wurzel = gruppenwurzel(elsel); if (wurzel == 0) {/* nur ein Element */ group[elsel] = 0; return; } for (i=1;i<=grumax;i++) { if (vater[i]==wurzel) { vater[i]=0; } } vater[wurzel]=-1; /*Gruppennummer wieder frei */ grumaxbestimmen(); /* Direkt an Wurzel haengende Eelemente vereinzeln */ for (i=1;i<=zelmax;i++) { if (group[i]==wurzel) group[i]=0; } } Static Void unbenutztegruppenfreigeben() { long elsel, g, gw; if (aenderunggruppen == false) return; aenderunggruppen = false; initgruppentag(false); for (elsel=1;elsel <= zelmax; elsel++) { if (typ[elsel] > 0) { g = group[elsel]; if (g != 0) gruppentag[g] = true; } } LL: ; for (g=1;g<=grumax;g++) { if (gruppentag[g] == true){ if (vater[g] == -1) vater[g] =0; if ((vater[g] > 0)&&(gruppentag[vater[g]] ==false)) { gruppentag[vater[g]] = true; goto LL; } } } /* nicht benoetigte Gruppen freigeben ! */ for (g=1;g<=grumax;g++) { if (gruppentag[g] == false) vater[g] = -1; } grumaxbestimmen(); } Static Void gruppenumbenennen() { /* es werden die Gruppen zur Umbenennung vorgesehen, deren Gruppentag */ /* true ist */ long i,imax,ineu,v,vneu,g; for (i=1;i<=grumax;i++) umbenennung[i] = i; if (selmenue[mgroupmode] == false) return; imax = grumax; for (i=1;i<=imax;i++) { if (gruppentag[i] == true) { g = freiegruppe(); gruppentag[g] = false; umbenennung[i] = g; aenderunggruppen = true; } } for (i=1;i<=imax;i++) { if (gruppentag[i] == true) { v = vater[i]; if (v != 0) vneu = umbenennung[v]; else vneu = 0; ineu = umbenennung[i]; vater[ineu] = vneu; } } } Static Void bestimmeneuegruppe(elsel) long elsel; { if (group[elsel] == 0) return; if (selmenue[mgroupmode] == true) group[elsel] = umbenennung[group[elsel]]; else group[elsel] = 0; } Static double ppabstand(x1, y1, x2, y2) double x1, y1, x2, y2; /* Abstand zweier Punkte */ { double dx, dy; dx = (x2 - x1); dy = (y2 - y1); return (sifsqrt(1.0, dx * dx + dy * dy)); } Static Void cursan(x, y) double x, y; /* Text-Cursor anschalten */ { double yrel; curs_x=x; curs_y=y; yrel=y-wzeichendescent; rechteckinverse(x,yrel,x+wzeichenbreite,yrel+wzeichenhoehe); } Static boolean nglw(a, b) double a, b; /* true, falls naeherungsweise gleiche Winkel */ { if (si_fabs(a - b) < 2.0) return true; else return false; } Static boolean nglx(a, b) double a, b; /* true, falls naeherungsweise gleiche Koordinaten */ { if (si_fabs(a - b) < 0.1) return true; else return false; } Static Void pskalieren(x, y, dx, dy, f) double *x, *y, dx, dy, f; /* Translation Punkt x,y um dx,dy, Skalierungsfaktor f*/ /* Ergebnis wieder in x,y */ { *x = (*x - xmittelzei) * f + xmittelzei + dx; *y = (*y - ymittelzei) * f + ymittelzei + dy; } Static Void ausmenueelement(); Static Void somenfontwahl(i) long i; { fontnummer = i; strcpy(menue[mfont],textfontlabel[fontnummer]); ausmenueelement(mfont); } Static Void setzeakttextfont(elsel) long elsel; { long fontart; fontart = linetype[elsel]; if (fontart < 0) fontart = 0; if (fontart >= ztextfonts) fontart = ztextfonts -1; somenfontwahl(fontart); } Static Void textparam(elsel) long elsel; /* Berechenbare Parameter fuer Texte bestimmen */ { double th, thh, tl, tlh, ll, rl, dy; long lage, fontart, lstr; fontart = linetype[elsel]; if (fontart < 0) fontart = 0; if (fontart >= ztextfonts) fontart = ztextfonts -1; laenge1[elsel] = strlen(texte[textno[elsel]]); lstr = siintround(laenge1[elsel]); tl = XTextWidth(text_font_info[fontart],texte[textno[elsel]],lstr); /*textbreite*/ tlh = 0.5 * tl; th = textzeichenascent[fontart]; /*texthoehe*/ thh = 0.5 * th; lage = (long)floor(si_fabs(laenge2[elsel]) + 0.2); if (lage > 8) {/*eigentlich Fehlerfall*/ lage = 0; laenge2[elsel] = 0.0; } switch (lage) { /*case*/ case 0: /*bl*/ ll = 0.0; dy = 0.0; break; case 1: /*cc*/ ll = tlh; dy = thh; break; case 2: /*rb*/ ll = tl; dy = 0.0; break; case 3: /*cb*/ ll = tlh; dy = 0.0; break; case 4: /*lt*/ ll = 0.0; dy = th; break; case 5: /*rt*/ ll = tl; dy = th; break; case 6: /*ct*/ ll = tlh; dy = th; break; case 7: /*lc*/ ll = 0.0; dy = thh; break; case 8: /*rc*/ ll = tl; dy = thh; break; } rl = tl - ll; x2[elsel] = x1[elsel] - ll; y2[elsel] = y1_[elsel] - dy; xb2[elsel] = x1[elsel] + rl * crw[elsel]; yb2[elsel] = y1_[elsel] + rl * srw[elsel]; xb1[elsel] = x1[elsel] - ll * crw[elsel]; yb1[elsel] = y1_[elsel] - ll * srw[elsel]; } Static Void skalieren(i, dx, dy, f) long i; double dx, dy, f; /* Skalieren Zeichnungselement i */ { pskalieren(&x1[i], &y1_[i], dx, dy, f); pskalieren(&x2[i], &y2[i], dx, dy, f); pskalieren(&xb1[i], &yb1[i], dx, dy, f); pskalieren(&xb2[i], &yb2[i], dx, dy, f); if (si_iabs(typ[i]) != ttext) { laenge1[i] *= f; laenge2[i] *= f; } else textparam(i); berechneminmax(i); } Static Void addtheorem(ca, sa, cb, sb, cab, sab) double ca, sa, cb, sb, *cab, *sab; { *cab = ca * cb - sa * sb; *sab = ca * sb + sa * cb; } Static Void ellpar(elsel, xm, ym, lx, ly, cr, sr) long elsel; double *xm, *ym, *lx, *ly, *cr, *sr; /* Parameter einer Ellipse zurueckgeben */ { *xm = x1[elsel]; *ym = y1_[elsel]; *lx = laenge1[elsel]; *ly = laenge2[elsel]; *cr = crw[elsel]; *sr = srw[elsel]; } Static Void translation(dx, dy, xp, yp, xpr_, ypr_) double dx, dy, xp, yp, *xpr_, *ypr_; /* Koord. von p in neuem Koord.system, das um dx,dy translatiert*/ { *xpr_ = xp - dx; *ypr_ = yp - dy; } Static Void rotation(cw, sw, xp, yp) double cw, sw, *xp, *yp; /*Koord. von p in neuem Koord.system, das positiv rotiert*/ { double hx, hy; hx = cw * *xp + sw * *yp; hy = cw * *yp - sw * *xp; *xp = hx; *yp = hy; } Static double winkel0(dx, dy, a, b) double dx, dy, a, b; /* Winkel von x_Achse zu Strecke von (0,0) zu (dx,dy) fuer Ellipse */ /* mit Hauptachsen a und b und Mittelpunkt (0,0) */ { double at, rm; if (dy == 0.0) { if (dx >= 0.0) at = 0.0; else at = wh; goto _L1; } if (dx == 0.0) { if (dy >= 0.0) at = wv; else at = wdv; goto _L1; } if (si_fabs(dy) > 10000.0 * si_fabs(dx)) { /*fast senkrecht*/ if (dy >= 0.0) at = wv; else at = wdv; goto _L1; } rm = si_fabs(a / b * (dy / dx)); at = fbograd * atan(rm); /*spezielle Winkelrichtung gemaess Quadrant*/ if (dx < 0.0 && dy > 0.0) at = wh - at; if (dx < 0.0 && dy < 0.0) at += wh; if (dx > 0.0 && dy < 0.0) at = wg - at; if (si_fabs(at) < 0.01) at = 0.0; if (si_fabs(at - wg) < 0.01) at = wg; _L1: return at; } Static double winkelk(xm, ym, xp, yp) double xm, ym, xp, yp; /* Winkel von x_Achse zu Strecke von (xm,ym) zu (xp,yp)*/ /*xm,ym Mittelpunkt Kreis*/ /* xp,yp Koordinaten eines Punktes */ { double dx, dy; translation(xm, ym, xp, yp, &dx, &dy); return (winkel0(dx, dy, 1.0, 1.0)); } Static Void setzewinkel(elsel, xm, ym, xp, yp) long elsel; double xm, ym, xp, yp; /* Berechne Drehwinkel des Zeichnungselementes elsel */ { rotwi[elsel] = winkelk(xm, ym, xp, yp); crw[elsel] = cos(fgradbo * rotwi[elsel]); srw[elsel] = sin(fgradbo * rotwi[elsel]); } Static Void ell_xy(xm, ym, a, b, cr, sr, xpr_, ypr_, xp, yp) double xm, ym, a, b, cr, sr, xpr_, ypr_, *xp, *yp; /* Umrechnung Punkt (xpr,ypr) im Ellipsenkoordinatensystem */ /* in das Weltkoordinatensystem, dort (xp,yp) */ { *xp = xpr_; *yp = ypr_; rotation(cr, -sr, xp, yp); /*Rotation um neg. Winkel*/ translation(-xm, -ym, *xp, *yp, xp, yp); } Static Void ellw_xy(xm, ym, a, b, cr, sr, w, xp, yp) double xm, ym, a, b, cr, sr, w, *xp, *yp; /* Punkt auf Ellipse durch Winkel w in Grad bei Ellipse definiert */ /* in Punkt (xp,yp) des Weltkoordinatensystems umrechnen */ { ell_xy(xm, ym, a, b, cr, sr, a * cos(w * fgradbo), b * sin(w * fgradbo), xp, yp); } Static Void xy_ell(xm, ym, cr, sr, xp, yp, xpr_, ypr_) double xm, ym, cr, sr, xp, yp, *xpr_, *ypr_; /*Transformation Punkt (xp,yp) in Weltkoordinaten in */ /*Koordinatensystem der Ellipse, dort (xpr,ypr)*/ { translation(xm, ym, xp, yp, xpr_, ypr_); rotation(cr, sr, xpr_, ypr_); /*Rotation um pos. Winkel*/ } Static double winkelell(xm, ym, a, b, cr, sr, xp, yp) double xm, ym, a, b, cr, sr, xp, yp; /* xm,ym,a,b,cr,sr definieren Ellipse*/ /* xp,yp Punkt in Zeichenebene */ /* Winkel gesucht im Bezugskoordinatensystem der Ellipse*/ { double dx, dy; xy_ell(xm, ym, cr, sr, xp, yp, &dx, &dy); return (winkel0(dx, dy, a, b)); } Static Void stdimagetextaus(twin, x, y, t, zcolor) Window twin; long zcolor; double x, y; Char *t; /* Ausgabe string t an Stelle x,y */ { long ix,iy,length; length=strlen(t); welt_to_bildschirm(x, y, &ix, &iy); setcolor(display,gcstd,zcolor); XDrawImageString(display,twin,gcstd,ix,iy,t,length); } Static Void stdtextaus(twin, x, y, t, zcolor) Window twin; long zcolor; double x, y; Char *t; /* Ausgabe string t an Stelle x,y */ { long ix,iy,length; length=strlen(t); welt_to_bildschirm(x, y, &ix, &iy); setcolor(display,gcstd,zcolor); XDrawString(display,twin,gcstd,ix,iy,t,length); } Static Void ztextaus(twin, elsel, x, y, t, zcolor, fontart) Window twin; long zcolor,fontart, elsel; double x, y; Char *t; /* Ausgabe string t an Stelle x,y in der Zeichnung */ { long ix,iy,length; length=strlen(t); welt_to_bildschirm(x, y, &ix, &iy); setcolor(display,gctext[fontart],zcolor); XDrawString(display,twin,gctext[fontart],ix,iy,t,length); } Static Void somentextaus(x, y, t, fontart) long fontart; double x, y; Char *t; /* Ausgabe string t an Stelle x,y in der Zeichnung */ { long ix,iy,lstr; double dx; lstr=strlen(t); dx = XTextWidth(text_font_info[fontart],t,lstr); welt_to_bildschirm(x-dx/2.0, y, &ix, &iy); XDrawString(display,win,somengctext[fontart],ix,iy,t,lstr); } Static Void ausfarbkaestchen(xa,ye,xe,ya,zcolor) double xa,ye,xe,ya; long zcolor; { long ix,iy,width,height; rechteckbildschirmkoord(xa,ye,xe,ya,&ix,&iy,&width,&height); setcolor(display,gcstd,zcolor); XFillRectangle(display,win,gcstd,ix,iy,width,height); } Static Void faerbekaestchen(i, zcolor) long i, zcolor; { ausfarbkaestchen(xam[i],yem[i],xem[i],yam[i],zcolor); } Static Void somenbestxy(i, xa,ya,xe,ye,xt,yt) long i; double *xa,*ya,*xe,*ye,*xt,*yt; { long reihe,spalte; reihe= i/somenspalten; spalte=i % somenspalten; *xa=spalte*kaestchenhoehe+1.0*wzeichenbreite; *ya=reihe*kaestchenhoehe+yprompt+1.5*wzeichenhoehe; *xe=*xa+kaestchenhoehe; *ye=*ya+kaestchenhoehe; *xt=*xa+kaestchenhoehe/2.0; *yt=*ya+kaestchenhoehe*0.1; } Static long somenbesti(x,y) double x,y; { long reihe,spalte; double xa,ya; xa=x-1.0*wzeichenbreite; ya=y-yprompt-1.5*wzeichenhoehe; if ((xa<0.0)||(ya<0.0)) return -1L; spalte=xa/kaestchenhoehe; reihe=ya/kaestchenhoehe; return (reihe*somenspalten+spalte); } Static Void aussomenue() { long i; double xa,ya,xe,ye,xt,yt; for (i=0;i= maxstrl) ls=maxstrl; ls = ls - strlen(promptzeile); while (ls > 0) { konkat(promptzeile,promptzeile,blank); ls--; } stdimagetextaus(win,xprompt, yprompt, promptzeile,schwarz); } Static Void gridpunkt(mstrich, nstrich, x, y) double mstrich,nstrich; double *x, *y; { *x = gridx0 + (mstrich * gridwx1 + nstrich * gridwx2) * gridw; *y = gridy0 + (mstrich * gridwy1 + nstrich * gridwy2) * gridw; } Static Void textpositionieren() /* Positionieren des Textes im Fensterausschnitt */ { long lsa, ls, lsmax, tposoffset, ogrenzeoffset; lsa = strlen(pr1)+strlen(pr2)+strlen(pr3)+strlen(pr4)+strlen(pr5); ls = strlen(EinText); lsmax = (long) floor((xzmax-xprompt)/wzeichenbreite)-3-lsa; ogrenzeoffset = ls - lsmax; if (ls <= lsmax) tposoffset = 0; else { tposoffset = tposres - lsmax/2; if (tposoffset < 0) tposoffset = 0; if (tposoffset > ogrenzeoffset) tposoffset = ogrenzeoffset; } substringcpy(pr6,EinText,tposoffset,lsmax); curs_x=xprompt+(tposres-tposoffset+lsa-1)*wzeichenbreite; curs_y=yprompt; if (geoeffnet==0) return; cursan(curs_x, curs_y); } Static Void inittastaturtext(s,prtext, voll) Char *s,*prtext; long voll; /* Eingabe Tastaturtext */ /* s ist Ergebnisstring, erst am Ende verfuegbar */ /* s muss initialisiert sein */ { long ls,dphase; Char csw[maxstrl+1]; erwartet=tastatur_erwartet; strcpy(tpr1res,pr1); strcpy(tpr2res,pr2); strcpy(tpr3res,pr3); strcpy(tpr4res,pr4); if (voll==0) { strcpy(pr1,nullstr); strcpy(pr2,nullstr); strcpy(pr3,nullstr); strcpy(pr4,nullstr); } strcpy(pr5,prtext); strcpy(EinText,s); ls = strlen(EinText); tposres = ls + 1; textpositionieren(); } Static long tastaturtext(taste) long taste; /* Eingabe Tastaturtext */ /* Ergebnis ==0: String fertig eingegeben */ /* Ergebnis !=0: String noch nicht mit Return abgeschlossen */ { long ls,lsa; Char csw[maxstrl+1]; lsa = strlen(pr1)+strlen(pr2)+strlen(pr3)+strlen(pr4)+strlen(pr5); ls = strlen(EinText); if ((taste == tastecursright1)|| (taste == tastecursright2)) { if (tposres <= ls) (tposres)++; goto L0A; } if ((taste == tastecursleft1)||(taste == tastecursleft2)) { if (tposres > 1) (tposres)--; goto L0A; } if ((taste==tasted)&&(controlan==1L)) {/*delete */ if (ls >= tposres) strdelete(EinText, (int)tposres); goto L0A; } if ((taste==tastea)&&(controlan==1L)) {/*an Anfang Zeile */ tposres = 1; goto L0A; } if ((taste==tastee)&&(controlan==1L)) {/*an Ende Zeile */ tposres = ls+1; goto L0A; } if ((taste==tastek)&&(controlan==1L)) {/*loeschen bis Ende Zeile */ EinText[tposres-1] = 0; goto L0A; } if (taste == tastebackspace || taste == tastedelete) { if (tposres > 1) { (tposres)--; strdelete(EinText, (int)tposres); } goto L0A; } if (taste == tastereturn) /*Return*/ goto LE; if (taste == 13) /*cr*/ goto LE; if (taste == 10) /*lf*/ goto LE; if (taste < 32) /*illegale Zeichen*/ goto L0A; if (taste >255) /*illegale Zeichen */ goto L0A; if (ls >= maxstrl) /*max stringlaenge erreicht*/ goto LE; sprintf(csw, "%c", (Char)taste); if (tposres <= ls) strinsert(csw, EinText, (int)tposres); else konkat(EinText, EinText,csw); (tposres)++; goto L0A; LE: strcpy(pr1,tpr1res); strcpy(pr2,tpr2res); strcpy(pr3,tpr3res); strcpy(pr4,tpr4res); strcpy(pr5,nullstr); strcpy(pr6,nullstr); erwartet=click_erwartet; return 0; L0A: textpositionieren(); return 1; } Static Void ausmenuetext(i,zcolor) /* Ausdruck eines Textes im Element i des Menues */ long i,zcolor; { double dx,dy; Char s[maxstrl+1]; dx=0.5*wzeichenbreite; dy=(si_fabs(yem[i]-yam[i])-wzeichenhoehe)/2.0; dy=0.8*dy + wzeichendescent; strcpy(s, menue[i]); stdtextaus(win,xam[i] + dx, yam[i] + dy,s,zcolor); } Static Void ausmenueelement(i) long i; { if ((selmenue[i]==true)&&(i!=mcolor)){ faerbekaestchen(i,schwarz); ausmenuetext(i, weiss); menuerechteck(xam[i],yam[i],xem[i],yem[i]); return; } if (i!=mcolor){ faerbekaestchen(i,weiss); ausmenuetext(i, schwarz); menuerechteck(xam[i],yam[i],xem[i],yem[i]); return; } faerbekaestchen(i,aktcolor); if (aktcolor==weiss) {ausmenuetext(i, schwarz); goto LW;} if (aktcolor==schwarz) {ausmenuetext(i, weiss); goto LW;} if (aktcolor <= (long) (letztesgrau/2)) {ausmenuetext(i, schwarz); goto LW;} if (aktcolor <= letztesgrau) {ausmenuetext(i, weiss); goto LW;} /* if (((rgbistdef[aktcolor].red & 0377) >100)|| ((rgbistdef[aktcolor].green & 0377)>100)|| ((rgbistdef[aktcolor].blue & 0377)>100)) */ if (intensity[aktcolor] > 0.5) ausmenuetext(i, schwarz); else ausmenuetext(i, weiss); LW: menuerechteck(xam[i],yam[i],xem[i],yem[i]); } Static long xyein(x, y, taste, phase) long phase,taste; double *x, *y; { long anz; double lgx, lgy; switch (phase){ case 0: goto L0; default: goto L1; } L0: inittastaturtext(nullstr,pr2menue[mxytastatur],1L); return 1; L1: anz=sscanf(EinText,"%lf%lf",&lgx,&lgy); if (anz!=2) {lgx=0; lgy=0;} /* lgx,lgy im Grid-Koordinatensystem, also umrechnen */ gridpunkt(lgx, lgy, x, y); selmenue[mxytastatur] = false; ausmenueelement((long)mxytastatur); return 0; } Static Void koeff_bezier(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y, bk) double p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y; tbezierkoeff *bk; { bk->dx = p0x; bk->cx = (p1x - p0x) * 3.0; bk->bx = (p2x - p1x) * 3.0 - bk->cx; bk->ax = p3x - p0x - bk->cx - bk->bx; bk->dreiax = 3.0 * bk->ax; bk->zweibx = 2.0 * bk->bx; bk->dy = p0y; bk->cy = (p1y - p0y) * 3.0; bk->by = (p2y - p1y) * 3.0 - bk->cy; bk->ay = p3y - p0y - bk->cy - bk->by; bk->dreiay = 3.0 * bk->ay; bk->zweiby = 2.0 * bk->by; } Static Void punkt_bezier(elsel, t, prx, pry) long elsel; double t, *prx, *pry; { double J0,J1,J2,J3,emt; emt = 1.0-t; J0=emt*emt*emt; J1=3.0*t*emt*emt; J2=3.0*t*t*emt; J3=t*t*t; *prx=x1[elsel]*J0+xb1[elsel]*J1+xb2[elsel]*J2+x2[elsel]*J3; *pry=y1_[elsel]*J0+yb1[elsel]*J1+yb2[elsel]*J2+y2[elsel]*J3; } Static Void ableitung_bezier(elsel, t, dxdt, dydt) long elsel; double t, *dxdt,*dydt; { double dJ0,dJ1,dJ2,dJ3,emt; emt = 1.0-t; dJ0=-3.0*emt*emt; dJ1=3.0*emt*emt-6.0*t*emt; dJ2=6.0*t*emt-3.0*t*t; dJ3=3.0*t*t; *dxdt= x1[elsel]*dJ0+xb1[elsel]*dJ1+xb2[elsel]*dJ2+x2[elsel]*dJ3; *dydt=y1_[elsel]*dJ0+yb1[elsel]*dJ1+yb2[elsel]*dJ2+y2[elsel]*dJ3; } Static double pbezabstand(elsel, xp, yp) long elsel; double xp, yp; { terg erg; tbezierkoeff bk; long i, anzt; double p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y, d, dmin, xb, yb; p0x = x1[elsel]; p0y = y1_[elsel]; p1x = xb1[elsel]; p1y = yb1[elsel]; p2x = xb2[elsel]; p2y = yb2[elsel]; p3x = x2[elsel]; p3y = y2[elsel]; dmin = ppabstand(p0x, p0y, xp, yp); d = ppabstand(p3x, p3y, xp, yp); if (d < dmin) dmin = d; koeff_bezier(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y, &bk); gldritterord(bk.ax, bk.bx, bk.cx, bk.dx - xp, &anzt, erg); for (i = 1; i <= anzt; i++) { if ((erg[i] >= 0.0)&&(erg[i] <= 1.0)) { /*Aenderung 19.12.92.*/ punkt_bezier(elsel, erg[i], &xb, &yb); d = ppabstand(xb, yb, xp, yp); if (d < dmin) dmin = d; } } gldritterord(bk.ay, bk.by, bk.cy, bk.dy - yp, &anzt, erg); for (i = 1; i <= anzt; i++) { if ((erg[i] >= 0.0)&&(erg[i] <= 1.0)) { /*Aenderung 19.12.92.*/ punkt_bezier(elsel, erg[i], &xb, &yb); d = ppabstand(xb, yb, xp, yp); if (d < dmin) dmin = d; } } return dmin; } Static long getlinedicke(i) long i; {long ldicke; ldicke=linedicke[i]; ldicke=ldicke % 100; if (ldicke > maxldicke) ldicke=maxldicke; return ldicke; } Static long getmenuecolor() { return aktcolor; } Static long getlinecolor(i) long i; {long lcolor; lcolor=schwarz; /*linecolor*/ if (linedicke[i] >=100) lcolor = linedicke[i]/100; return lcolor; } Static long getzcolor(i, painterase) long i, painterase; { long lcolor, zcolor; lcolor = getlinecolor(i); /*Farbe der Linie*/ zcolor = weiss; /*Farbe, die zu zeichnen*/ if (painterase==paint) zcolor=lcolor; return zcolor; } Static Void getlineattribute(i, elemtyp, ltyp, ldicke, lende, lcolor) long i, elemtyp, *ltyp, *ldicke, *lende, *lcolor; { if (i == 0) { *lende = 0; /*kein Pfeil*/ if (selmenue[mpfeilende]==true) /*Pfeil am Ende*/ *lende = 2; if (selmenue[mpfeilanf]==true) /*Pfeil am Anfang*/ *lende = 1; if ((selmenue[mpfeilanf]==true) && (selmenue[mpfeilende]==true)) *lende = 3; *ldicke = aktldicke; /*eingestellte Linienstaerke*/ *ltyp = 1; /*solid*/ if (selmenue[mgestrichelt]==true) /*_ _ */ *ltyp = 5; if (selmenue[mgepunktet]==true) /*....*/ *ltyp = 3; if ((selmenue[mgestrichelt]==true) && (selmenue[mgepunktet]==true)) /*_._*/ *ltyp = 7; if ((selmenue[mcapprojecting] == true)&&(elemtyp == tgerade)&& (*lende == 0)&&(*ltyp == 1)) *lende = 4; /*cap projecting */ *lcolor = getmenuecolor(); return; } *ltyp = linetype[i]; *ldicke = getlinedicke(i); *lende = lineende[i]; *lcolor = getlinecolor(i); } Static Void setlineattribute(i, elsel) long i, elsel; {long ltyp, ldicke, lende, lcolor; getlineattribute(i, typ[elsel], <yp, &ldicke, &lende, &lcolor); if (typ[elsel] != ttext) linetype[elsel] = ltyp; linedicke[elsel] = 100*lcolor+ldicke; lineende[elsel] = lende; } Static Void winpfeilaus(i, ende, xp, yp, x2, y2,zcolor) long i, ende,zcolor; double xp, yp, x2, y2; /* Pfeilspitze an xp,yp */ /* Pfeilende in Richtung Punkt x2,y2 */ /* ende=1 fuer Anfang, ende=2 fuer Ende */ { double d,lpf,bpf,sg,cg; XPoint points[maxpunkte]; switch (lineende[i]){ case 0: return; case 1: if (ende!=1) return; break; case 2: if (ende!=2) return; break; case 3: break; case 4: return; } lpf=6.0+0.8*getlinedicke(i);/*Laenge Pfeil*/ bpf=(4.0+1.2*getlinedicke(i))*0.5;/*halbe Breite Pfeil*/ d=ppabstand(xp,yp,x2,y2); if (d==0) return; sg=(y2-yp)/d; cg=(x2-xp)/d; rpxarray[0] = xp; rpyarray[0] = yp; rpxarray[1] = xp+(cg*lpf-sg*bpf); rpyarray[1] = yp+(sg*lpf+cg*bpf); rpxarray[2] = xp+(cg*lpf+sg*bpf); rpyarray[2] = yp+(sg*lpf-cg*bpf); rpxarray[3] = xp; rpyarray[3] = yp; ausfillpolygon(4L,zcolor); } Static Void winpfeile(i,zcolor) long i, zcolor; { double xm, ym, lx, ly, cr, sr,xp1,xp2,yp1,yp2; switch (typ[i]) { case tgerade: winpfeilaus(i, 1L,x1[i],y1_[i],x2[i],y2[i],zcolor); winpfeilaus(i, 2L,x2[i],y2[i],x1[i],y1_[i],zcolor); break; case tkreisbogen: case tellbogen: ellpar(i,&xm,&ym,&lx,&ly,&cr,&sr); ellw_xy(xm,ym,lx,ly,cr,sr,wanf[i],&xp1,&yp1); ellw_xy(xm,ym,lx,ly,cr,sr,wanf[i]+50,&xp2,&yp2); winpfeilaus(i,1L,xp1,yp1,xp2,yp2,zcolor); ellw_xy(xm,ym,lx,ly,cr,sr,wend[i],&xp1,&yp1); ellw_xy(xm,ym,lx,ly,cr,sr,wend[i]-50,&xp2,&yp2); winpfeilaus(i,2L,xp1,yp1,xp2,yp2,zcolor); break; case tbezier: winpfeilaus(i, 1L, x1[i],y1_[i],xb1[i],yb1[i],zcolor); winpfeilaus(i, 2L, x2[i],y2[i],xb2[i],yb2[i],zcolor); break; }/*case*/ } Static Void auspolyline(zcolor,elsel,anzp) long zcolor,elsel,anzp; /* Koordinaten 1..anzp in rpxarray und rpyarray*/ /* elsel fuer Liniendefinition */ /* falls elsel = 0 dann Standardattribute verwenden */ { long ldicke,lende,ltyp,lcolor,ix,iy,k; double xx,yy; XPoint points[maxpunkte]; for (k=0;k= maxpunkte-2) fehler(4L); return; } x12 = (x1+x2)*0.5; y12 = (y1+y2)*0.5; x34 = (x3+x4)*0.5; y34 = (y3+y4)*0.5; x1223 = (x12+x23)*0.5; y1223 = (y12+y23)*0.5; x2334 = (x23+x34)*0.5; y2334 = (y23+y34)*0.5; x12232334 = (x1223+x2334)*0.5; y12232334 = (y1223+y2334)*0.5; bezierpunkte(x1,y1,x12,y12,x1223,y1223,x12232334,y12232334,anzp); bezierpunkte(x12232334,y12232334,x2334,y2334,x34,y34,x4,y4,anzp); } Static Void minmaxbezier(elsel,anzp) long elsel, anzp; { long i; elxmin[elsel]=rpxarray[0]; elxmax[elsel]=rpxarray[0]; elymin[elsel]=rpyarray[0]; elymax[elsel]=rpyarray[0]; for (i=1;i elxmax[elsel]) elxmax[elsel]=rpxarray[i]; if (rpyarray[i] > elymax[elsel]) elymax[elsel]=rpyarray[i]; } } Static Void ausbezier(elsel,zcolor) long elsel,zcolor; { long anzp; anzp = 0; bezierpunkte(x1[elsel],y1_[elsel],xb1[elsel],yb1[elsel], xb2[elsel],yb2[elsel],x2[elsel],y2[elsel],&anzp); rpxarray[anzp] = x2[elsel]; rpyarray[anzp] = y2[elsel]; anzp++; minmaxbezier(elsel,anzp); auspolyline(zcolor,elsel,anzp); } Static Void ausbeziergef(elsel,zcolor) long elsel,zcolor; { long anzp; anzp = 0; bezierpunkte(x1[elsel],y1_[elsel],xb1[elsel],yb1[elsel], xb2[elsel],yb2[elsel],x2[elsel],y2[elsel],&anzp); rpxarray[anzp] = x2[elsel]; rpyarray[anzp] = y2[elsel]; anzp++; minmaxbezier(elsel,anzp); ausfillpolygon(anzp, zcolor); } Static Void kaestchen(i, anteil, teilung, pos) long i, anteil, teilung, *pos; { long zeile, platz; double dx, dy; if (*pos == 0) *pos = 11; zeile = (long)(*pos / 10.0); platz = *pos - zeile * 10; dx = (xem[0] - xam[0]) / teilung; dy = si_fabs(yem[0] - yam[0]); xam[i] = xam[0] + (platz - 1) * dx; xem[i] = xam[i] + anteil * dx; if (si_fabs(xem[i]-xem[0]) < 1.0) xem[i]=xem[0]; yem[i] = yem[0] - zeile * dy; yam[i] = yam[0] - zeile * dy; platz += anteil; if (platz > teilung) { zeile++; platz = 1; } *pos = zeile * 10 + platz; } Static Void init_tmenue() { long i; for (i = 1; i <= zmenue; i++) strcpy(pr2menue[i], blank); for (i = 1; i <= zmenue; i++) strcpy(pr3menue[i], blank); strcpy(menue[mende], "quit"); strcpy(pr2menue[mende],intfiletext); strcpy(pr3menue[mende],extfiletext); radiogroup[mende] = 1; strcpy(menue[mladen], "load"); strcpy(pr2menue[mladen],"input file:"); radiogroup[mladen] = 1; strcpy(menue[msave], "save"); strcpy(pr2menue[msave],intfiletext); strcpy(pr3menue[msave],extfiletext); radiogroup[msave] = 1; strcpy(menue[mtext], "text"); strcpy(pr2menue[mtext], " position?"); strcpy(pr3menue[mtext], "?:"); radiogroup[mtext] = 1; strcpy(menue[mgerade], "line"); strcpy(pr2menue[mgerade], " point 1?"); strcpy(pr3menue[mgerade], " point 2?"); radiogroup[mgerade] = 1; strcpy(menue[mkreis], "circle"); strcpy(pr2menue[mkreis], " center point?"); strcpy(pr3menue[mkreis], " point on circle?"); radiogroup[mkreis] = 1; strcpy(menue[mell], "ellipse"); strcpy(pr2menue[mell], " center point?"); strcpy(pr3menue[mell], prxachse); radiogroup[mell] = 1; strcpy(menue[mrechteck], "rectangle"); strcpy(pr2menue[mrechteck], " corner 1?"); strcpy(pr3menue[mrechteck], " corner 2?"); radiogroup[mrechteck] = 1; strcpy(menue[mdreieck], "triangle"); strcpy(pr2menue[mdreieck], " point 1?"); strcpy(pr3menue[mdreieck], " point 2?"); radiogroup[mdreieck] = 1; strcpy(menue[mviereck], "quadrangle"); strcpy(pr2menue[mviereck], " point 1?"); strcpy(pr3menue[mviereck], " point 2?"); radiogroup[mviereck] = 1; strcpy(menue[mbezier], "Bezier"); strcpy(pr2menue[mbezier], " starting point?"); strcpy(pr3menue[mbezier], " end point?"); radiogroup[mbezier] = 1; strcpy(menue[mpolygon], "polygon"); strcpy(pr2menue[mpolygon], " center point?"); strcpy(pr3menue[mpolygon], " point on circle?"); radiogroup[mpolygon] = 1; strcpy(menue[mspiegeln], "mirror"); strcpy(pr2menue[mspiegeln], " mirror line?"); strcpy(pr3menue[mspiegeln], " object(s)?"); radiogroup[mspiegeln] = 1; strcpy(menue[mkopieren], "copy"); strcpy(pr2menue[mkopieren], " reference line?"); strcpy(pr3menue[mkopieren], " destination line?"); radiogroup[mkopieren] = 1; strcpy(menue[mkopbewmaus], "m"); strcpy(pr2menue[mkopbewmaus], " reference point?"); strcpy(pr3menue[mkopbewmaus], " destination point?"); radiogroup[mkopbewmaus] = 0; strcpy(menue[mbewegen], "move"); strcpy(pr2menue[mbewegen], " reference line?"); strcpy(pr3menue[mbewegen], " destination line?"); radiogroup[mbewegen] = 1; strcpy(menue[mergaenzen], "complete"); strcpy(pr2menue[mergaenzen], " line 1?"); strcpy(pr3menue[mergaenzen], " line 2?"); radiogroup[mergaenzen] = 1; strcpy(menue[mausdehnen], "extend"); strcpy(pr2menue[mausdehnen], " line/arc?"); radiogroup[mausdehnen] = 1; strcpy(menue[mbrechen], "trim"); strcpy(pr2menue[mbrechen], " remove part?"); radiogroup[mbrechen] = 1; strcpy(menue[mloeschen], "delete"); strcpy(pr2menue[mloeschen], " object(s)?"); radiogroup[mloeschen] = 1; strcpy(menue[mup], "up"); strcpy(pr2menue[mup], "/reverse print order, object(s)?"); radiogroup[mup] = 1; strcpy(menue[mdown], "down"); strcpy(pr2menue[mdown], "/put in background, object(s) ?"); radiogroup[mdown] = 1; strcpy(menue[meinrasten], "snap"); radiogroup[meinrasten] = 0; strcpy(menue[mgefuellt], "*"); radiogroup[mgefuellt] = 0; strcpy(menue[mbogen], "C"); radiogroup[mbogen] = 0; strcpy(menue[mparallel], "||"); strcpy(pr2menue[mparallel], " direction of end point?"); strcpy(pr3menue[mparallel], " parallel line?"); radiogroup[mparallel] = 2; strcpy(menue[mlot], "-|"); strcpy(pr3menue[mlot], " line for normal?"); radiogroup[mlot] = 2; strcpy(menue[mmittelpunkt], "mp"); strcpy(pr2menue[mmittelpunkt], " (mp for center of object)"); radiogroup[mmittelpunkt] = 0; strcpy(menue[mpfeilanf], "b>"); radiogroup[mpfeilanf] = 0; strcpy(menue[mpfeilende], "e>"); radiogroup[mpfeilende] = 0; strcpy(menue[mdick], "=="); radiogroup[mdick] = 0; strcpy(menue[mgestrichelt], " _"); radiogroup[mgestrichelt] = 0; strcpy(menue[mgepunktet], " ."); radiogroup[mgepunktet] = 0; strcpy(menue[mlschieben], "<"); strcpy(pr2menue[mlschieben], " picture moves left"); radiogroup[mlschieben] = 0; strcpy(menue[moschieben], "^"); strcpy(pr2menue[moschieben], " picture moves up"); radiogroup[moschieben] = 0; strcpy(menue[muschieben], "v"); strcpy(pr2menue[muschieben], " picture moves down"); radiogroup[muschieben] = 0; strcpy(menue[mrschieben], ">"); strcpy(pr2menue[mrschieben], " picture moves right"); radiogroup[mrschieben] = 0; strcpy(menue[mredraw], "[]"); strcpy(pr2menue[mredraw], " redraw"); radiogroup[mredraw] = 0; strcpy(menue[mgitter], "G"); strcpy(pr2menue[mgitter], " grid origin?"); radiogroup[mgitter] = 1; strcpy(menue[mcenter], "o"); strcpy(pr2menue[mcenter], " picture to center"); radiogroup[mcenter] = 0; strcpy(menue[mgross], "+"); strcpy(pr2menue[mgross], " zooming in"); radiogroup[mgross] = 0; strcpy(menue[mklein], "-"); strcpy(pr2menue[mklein], " zooming out"); radiogroup[mklein] = 0; strcpy(menue[mxytastatur], " xy"); strcpy(pr2menue[mxytastatur], " key input of point in grid coordinates:"); radiogroup[mxytastatur] = 0; strcpy(menue[mltext], "l"); radiogroup[mltext] = 4; strcpy(menue[mrtext], "r"); radiogroup[mrtext] = 4; strcpy(menue[mbtext], "b"); radiogroup[mbtext] = 5; strcpy(menue[mttext], "t"); radiogroup[mttext] = 5; strcpy(menue[mfont], nullstr); radiogroup[mfont] = 0; strcpy(menue[mcut], "cut"); strcpy(pr2menue[mcut]," reference point?"); radiogroup[mcut] = 1; strcpy(menue[mpaste], "paste"); strcpy(pr2menue[mpaste]," destination point?"); radiogroup[mpaste] = 1; strcpy(menue[mcolor], "color"); radiogroup[mcolor] = 0; strcpy(menue[mchangelineattr], "chatt"); strcpy(pr2menue[mchangelineattr], " set attributes to change (= _ . b> e> |] font color l r b t) then select object(s)?"); radiogroup[mchangelineattr] = 1; strcpy(menue[mdegrees], "deg"); strcpy(pr2menue[mdegrees], " input angle in degrees:"); radiogroup[mdegrees] = 0; strcpy(menue[mfill], "fill"); strcpy(pr2menue[mfill], " circle, ellipse, arc or first line (to define triangle or quadrangle)?"); strcpy(pr3menue[mfill], " second line (to define triangle or quadrangle)?"); radiogroup[mfill] = 1; strcpy(menue[mgroupmode], "groupmode"); radiogroup[mgroupmode] = 0; strcpy(menue[mnewgroup], "newgroup"); strcpy(pr2menue[mnewgroup], " first(next) group to combine defined by object(s)?"); radiogroup[mnewgroup] = 1; strcpy(menue[mungroup], "ungroup"); strcpy(pr2menue[mungroup], " group defined by object?, OK to ungroup"); radiogroup[mungroup] = 1; strcpy(menue[mshowgroup], "showgroup"); strcpy(pr2menue[mshowgroup], " group defined by object?"); radiogroup[mshowgroup] = 1; strcpy(menue[mgroupok], "OK"); strcpy(pr2menue[mgroupok], " group ok"); radiogroup[mgroupok] = 0; strcpy(menue[mconnect], "connect"); strcpy(pr2menue[mconnect], " (not all object types allowed) object1?"); strcpy(pr3menue[mconnect], " (not all object types allowed) object2 or point?"); radiogroup[mconnect] = 1; strcpy(menue[mconnxy], "X"); radiogroup[mconnxy] = 6; strcpy(menue[mconnyx], "Y"); radiogroup[mconnyx] = 6; strcpy(menue[mconnpoint], "p"); strcpy(menue[mqueryattr], "attr?"); strcpy(pr2menue[mqueryattr], " (color, font, linewidth) object?"); radiogroup[mqueryattr] = 1; radiogroup[mconnpoint] = 0; strcpy(menue[mrot], "rotate"); strcpy(pr2menue[mrot], " degrees, object(s)?"); strcpy(pr3menue[mrot], " degrees, pivot point?"); radiogroup[mrot] = 1; strcpy(menue[mcapprojecting], "|]"); radiogroup[mcapprojecting] = 0; strcpy(menue[mwinkelrot], ""); radiogroup[mwinkelrot] = 0; strcpy(menue[mread], "stdin"); strcpy(pr2menue[mread]," "); radiogroup[mread] = 1; strcpy(menue[mreadzeit], ""); radiogroup[mreadzeit] = 0; /* maximale Nr. bei radiogroup ist 6 */ /* 1 fuer normale Menueeintraege */ /* 0 fuer Voreinstellungen */ } Static Void init_kmenue() { long pos,i; double dy; xam[0] = xgrf+1.0*wzeichenbreite; xem[0] = xam[0]+kaestchenbreite; yam[0] = yzmax - 0.5*kaestchenhoehe; yem[0] = yam[0]+ kaestchenhoehe; /* Reihenfolge des Aufrufs gibt Reihenfolge der Anordnung */ /* 2. und 3. Parameter bei kaestchen: anteil, teilung */ pos = 0; kaestchen((long)mtext, 1L, 2L, &pos); kaestchen((long)mfont, 1L, 2L, &pos); kaestchen((long)mgerade, 1L, 2L, &pos); kaestchen((long)mkreis, 1L, 2L, &pos); kaestchen((long)mell, 1L, 1L, &pos); kaestchen((long)mrechteck, 1L, 1L, &pos); kaestchen((long)mdreieck, 1L, 1L, &pos); kaestchen((long)mviereck, 1L, 1L, &pos); kaestchen((long)mbezier, 1L, 1L, &pos); kaestchen((long)mpolygon, 1L, 1L, &pos); kaestchen((long)mconnect, 5L, 8L, &pos); kaestchen((long)mconnpoint, 1L, 8L, &pos); kaestchen((long)mconnxy, 1L, 8L, &pos); kaestchen((long)mconnyx, 1L, 8L, &pos); kaestchen((long)mspiegeln, 1L, 2L, &pos); kaestchen((long)mqueryattr, 1L, 2L, &pos); kaestchen((long)mrot, 2L, 3L, &pos); kaestchen((long)mwinkelrot, 1L, 3L, &pos); kaestchen((long)mkopbewmaus, 1L, 8L, &pos); kaestchen((long)mkopieren, 3L, 8L, &pos); kaestchen((long)mbewegen, 4L, 8L, &pos); kaestchen((long)mergaenzen, 1L, 1L, &pos); kaestchen((long)mausdehnen, 1L, 2L, &pos); kaestchen((long)mbrechen, 1L, 2L, &pos); kaestchen((long)mloeschen, 1L, 2L, &pos); kaestchen((long)mfill, 1L, 2L, &pos); kaestchen((long)mup, 1L, 2L, &pos); kaestchen((long)mdown, 1L, 2L, &pos); kaestchen((long)mcut, 1L, 2L, &pos); kaestchen((long)mpaste, 1L, 2L, &pos); kaestchen((long)mltext, 1L, 4L, &pos); kaestchen((long)mrtext, 1L, 4L, &pos); kaestchen((long)mbtext, 1L, 4L, &pos); kaestchen((long)mttext, 1L, 4L, &pos); kaestchen((long)mgefuellt, 1L, 4L, &pos); kaestchen((long)mbogen, 1L, 4L, &pos); kaestchen((long)mparallel, 1L, 4L, &pos); kaestchen((long)mlot, 1L, 4L, &pos); kaestchen((long)mmittelpunkt, 1L, 4L, &pos); kaestchen((long)mpfeilanf, 1L, 4L, &pos); kaestchen((long)mpfeilende, 1L, 4L, &pos); kaestchen((long)mcapprojecting, 1L, 4L, &pos); kaestchen((long)mdick, 1L, 3L, &pos); kaestchen((long)mgestrichelt, 1L, 3L, &pos); kaestchen((long)mgepunktet, 1L, 3L, &pos); kaestchen((long)mgroupmode, 1L, 1L, &pos); kaestchen((long)mnewgroup, 1L, 1L, &pos); kaestchen((long)mungroup, 3L, 4L, &pos); kaestchen((long)mgroupok, 1L, 4L, &pos); kaestchen((long)mshowgroup, 1L, 1L, &pos); kaestchen((long)mlschieben, 1L, 5L, &pos); kaestchen((long)moschieben, 1L, 5L, &pos); kaestchen((long)mredraw, 1L, 5L, &pos); kaestchen((long)muschieben, 1L, 5L, &pos); kaestchen((long)mrschieben, 1L, 5L, &pos); kaestchen((long)mgitter, 1L, 4L, &pos); kaestchen((long)mcenter, 1L, 4L, &pos); kaestchen((long)mgross, 1L, 4L, &pos); kaestchen((long)mklein, 1L, 4L, &pos); kaestchen((long)meinrasten, 1L, 3L, &pos); kaestchen((long)mxytastatur, 1L, 3L, &pos); kaestchen((long)mdegrees, 1L,3L, &pos); kaestchen((long)mcolor, 1L, 1L, &pos); kaestchen((long)mread, 1L, 2L, &pos); kaestchen((long)mreadzeit, 1L, 2L, &pos); kaestchen((long)mchangelineattr, 1L,2L, &pos); kaestchen((long)mladen, 1L, 2L, &pos); kaestchen((long)msave, 1L, 2L, &pos); kaestchen((long)mende, 1L, 2L, &pos); dy=yprompt+1.5*wzeichenhoehe-yam[mende]; for (i=1;i<=zmenue;i++) {yam[i] += dy; yem[i] += dy;} } Static Void ausmenue() /* Ausdruck des Menues */ { long i; for (i = 1; i <= zmenue; i++) ausmenueelement(i); aussomenue(); } Static Void mstrnstr(x, y, mstr, nstr) double x, y; long *mstr, *nstr; { double dx, dy, f; dx = x - gridx0; dy = y - gridy0; f = 1 / ((gridwx1 * gridwy2 - gridwx2 * gridwy1) * gridw); *mstr = (long)floor((dx * gridwy2 - dy * gridwx2) * f + 0.5); *nstr = (long)floor((dy * gridwx1 - dx * gridwy1) * f + 0.5); } Static Void gridsnap(x, y) double *x, *y; { long mstrich, nstrich; double xx,yy; mstrnstr(*x, *y, &mstrich, &nstrich); gridpunkt((double)mstrich, (double)nstrich, &xx, &yy); *x=xx; *y=yy; } Static Void naehe(x1, y1, x2, y2, xmin, ymin, min) double x1, y1, x2, y2, *xmin, *ymin, *min; { double d, dx, dy; dx = si_fabs(x2 - x1); if (dx >= *min) return; dy = si_fabs(y2 - y1); if (dy >= *min) return; d = ppabstand(x1, y1, x2, y2); if (d >= *min) return; *min = d; *xmin = x1; *ymin = y1; } Static Void elsnap(x, y) double *x, *y; { long i; double xg, yg, xmin, ymin, min; Static boolean relevant(); min = 5.0; xmin = *x; ymin = *y; xg = *x; yg = *y; gridsnap(&xg, &yg); naehe(xg, yg, *x, *y, &xmin, &ymin, &min); for (i = 1; i <= zelmax; i++) { if (typ[i] > 0) { if (relevant(i, *x, *y)==true) { naehe(x1[i], y1_[i], *x, *y, &xmin, &ymin, &min); switch (typ[i]) { case tgerade: /*Gerade*/ naehe(x2[i], y2[i], *x, *y, &xmin, &ymin, &min); break; case trechteckgef: case tviereckgef: naehe(x2[i], y2[i], *x, *y, &xmin, &ymin, &min); naehe(xb1[i], yb1[i], *x, *y, &xmin, &ymin, &min); naehe(xb2[i], yb2[i], *x, *y, &xmin, &ymin, &min); break; case tdreieckgef: naehe(x2[i], y2[i], *x, *y, &xmin, &ymin, &min); naehe(xb1[i], yb1[i], *x, *y, &xmin, &ymin, &min); break; case tkreisbogen: case tellbogen: /*Bogen*/ case tkreissektorgef: case tellsektorgef: naehe(xb1[i], yb1[i], *x, *y, &xmin, &ymin, &min); naehe(xb2[i], yb2[i], *x, *y, &xmin, &ymin, &min); break; case tbezier: /*Bezier*/ case tbeziergef: naehe(x2[i], y2[i], *x, *y, &xmin, &ymin, &min); break; }/*case*/ }/*if relevant */ } /*if,for*/ } *x = xmin; *y = ymin; } Static Void marklinie(ix,iy,idx,idy,zcolor) long zcolor,ix,iy,idx,idy; { setvalues(display,gczeichnung,zcolor,0L,0L,0L); XDrawLine(display,win,gczeichnung,ix-idx,iy-idy,ix+idx,iy+idy); } Static Void ausmarken(anzp, mtyp, mhoehe, zcolor) long anzp, mtyp, zcolor; double mhoehe; /* Koordinaten in rpxarray,rpyarray */ { long i,ix,iy,imhoehe; double xx,yy; XPoint points[maxpunkte],tpoints[10]; imhoehe = siintround(mhoehe); if (anzp==0) return; for (i=0;i *imax) *imax = i; if (j < *jmin) *jmin = j; if (j > *jmax) *jmax = j; } Static Void ausgrid(zcolor) long zcolor; { long i, j, imin, jmin, imax, jmax, nn; double x, y, hoehemarke; nn = 0; hoehemarke = 2.0; einemarkeaus(gridx0, gridy0, 3L,hoehemarke, zcolor); /*fuer Zentrum */ mstrnstr(xgr, yprompt, &i, &j); imin = i; imax = i; jmin = j; jmax = j; ijminmax(xgr, yzmax, &imin, &imax, &jmin, &jmax); ijminmax(xzmax, yprompt, &imin, &imax, &jmin, &jmax); ijminmax(xzmax, yzmax, &imin, &imax, &jmin, &jmax); hoehemarke = 1.0; for (j = jmin; j <= jmax; j++) { for (i = imin; i <= imax; i++) { gridpunkt((double)i, (double)j, &x, &y); rpxarray[nn]=x; rpyarray[nn]=y; nn++; if (nn >= maxpunkte) { ausmarken(nn,1L,hoehemarke,zcolor); nn = 0; } } } if (nn > 0) ausmarken(nn,1L,hoehemarke,zcolor); } /*ausgrid*/ Static Void elskalieren(gridw, dxx, dyy, f) double *gridw, dxx, dyy, f; { long i; double dx, dy; if (f != 1.0) { *gridw = f * *gridw; while (*gridw > 1.5 * gridw0) *gridw /= 2.0; while (*gridw < 0.6 * gridw0) *gridw = 2.0 * *gridw; } i = (long)floor(dxx / *gridw + 0.5); dx = i * *gridw; i = (long)floor(dyy / *gridw + 0.5); dy = i * *gridw; /* fuer readstdin vermerken, welche Skalierungen durchgef"uhrt wurden */ readdxx = readdxx*f +dx; readdyy = readdyy*f +dy; readf = readf*f; /* jetzt eigentliche Skalierung */ for (i = 1; i <= zelmax; i++) { if (typ[i] != 0) skalieren(i, dx, dy, f); } for (i = 1; i <= 4; i++) { if (bmarker[i]==true) pskalieren(&xmarker[i], &ymarker[i], dx, dy, f); } pskalieren(&xlast, &ylast, dx, dy, f); pskalieren(&gridx0, &gridy0, dx, dy, f); } Static Void minmax(xmin, xmax, ymin, ymax) double *xmin, *xmax, *ymin, *ymax; { long i; boolean erstes; *xmax = 0.0; *ymax = 0.0; *xmin = 0.0; *ymin = 0.0; erstes = true; for (i = 1; i <= zelmax; i++) { if (typ[i] > 0) { /*i*/ if (erstes==true) { *xmax = elxmax[i]; *ymax = elymax[i]; *xmin = elxmin[i]; *ymin = elymin[i]; erstes = false; } if (elxmax[i] > *xmax) *xmax = elxmax[i]; if (elymax[i] > *ymax) *ymax = elymax[i]; if (elxmin[i] < *xmin) *xmin = elxmin[i]; if (elymin[i] < *ymin) *ymin = elymin[i]; } } } Static boolean inwinkel(elsel, w) long elsel; double w; { boolean erg; double wa, we; erg = false; wa = wanf[elsel]; we = wend[elsel]; if (si_fabs(wa - w) < 5.0) erg = true; if (si_fabs(we - w) < 5.0) erg = true; if (we > wa) { if (w >= wa && w <= we) erg = true; } if (we <= wa) { if (w <= we || w >= wa) erg = true; } return erg; } Static Void initgrenzen(xp,yp,xxmax,xxmin,yymax,yymin) double xp,yp,*xxmax,*xxmin,*yymax,*yymin; { *xxmax = xp; *xxmin = xp; *yymax = yp; *yymin = yp; } Void grenzen(xp,yp,xxmax,xxmin,yymax,yymin) double xp, yp, *xxmax,*xxmin,*yymax,*yymin; { if (xp > *xxmax) *xxmax = xp; if (xp < *xxmin) *xxmin = xp; if (yp > *yymax) *yymax = yp; if (yp < *yymin) *yymin = yp; } Static Void ellgrenzpunkte(i,xxmax,xxmin,yymax,yymin) long i; double *xxmax,*xxmin,*yymax,*yymin; { double xm,ym,lx,ly,cr,sr; double xg1,yg1,w1,xg2,yg2,w2,xg3,yg3,w3,xg4,yg4,w4; double h1,h2,h3,h4,h5; ellpar(i,&xm,&ym,&lx,&ly,&cr,&sr); h1 = lx*lx*cr*cr+ly*ly*sr*sr; h2 = ly*ly*cr*cr+lx*lx*sr*sr; h3 = cr*sr*(lx*lx-ly*ly); h4 = sqrt(h1); h5 = sqrt(h2); xg1 = xm + h4; xg2 = xm - h4; yg1 = ym + h4*h3/h1; yg2 = ym - h4*h3/h1; w1 = winkelell(xm, ym, lx, ly, cr, sr, xg1, yg1); w2 = winkelell(xm, ym, lx, ly, cr, sr, xg2, yg2); yg3 = ym + h5; yg4 = ym - h5; xg3 = xm + h5*h3/h2; xg4 = xm - h5*h3/h2; w3 = winkelell(xm, ym, lx, ly, cr, sr, xg3, yg3); w4 = winkelell(xm, ym, lx, ly, cr, sr, xg4, yg4); if (inwinkel(i,w1)==true) grenzen(xg1,yg1,xxmax,xxmin,yymax,yymin); if (inwinkel(i,w2)==true) grenzen(xg2,yg2,xxmax,xxmin,yymax,yymin); if (inwinkel(i,w3)==true) grenzen(xg3,yg3,xxmax,xxmin,yymax,yymin); if (inwinkel(i,w4)==true) grenzen(xg4,yg4,xxmax,xxmin,yymax,yymin); } Static Void berechneminmax(i) long i; { double xxmin,yymin,xxmax,yymax; double xm,ym,lx,ly,cr,sr; if (typ[i] <= 0) return; switch (typ[i]) { case ttext: initgrenzen(x1[i], y1_[i],&xxmax,&xxmin,&yymax,&yymin); grenzen(xb1[i], yb1[i],&xxmax,&xxmin,&yymax,&yymin); grenzen(xb2[i], yb2[i],&xxmax,&xxmin,&yymax,&yymin); break; case tgerade: initgrenzen(x1[i], y1_[i],&xxmax,&xxmin,&yymax,&yymin); grenzen(x2[i], y2[i],&xxmax,&xxmin,&yymax,&yymin); break; case trechteckgef: case tviereckgef: initgrenzen(x1[i], y1_[i],&xxmax,&xxmin,&yymax,&yymin); grenzen(x2[i], y2[i],&xxmax,&xxmin,&yymax,&yymin); grenzen(xb1[i], yb1[i],&xxmax,&xxmin,&yymax,&yymin); grenzen(xb2[i], yb2[i],&xxmax,&xxmin,&yymax,&yymin); break; case tdreieckgef: initgrenzen(x1[i], y1_[i],&xxmax,&xxmin,&yymax,&yymin); grenzen(x2[i], y2[i],&xxmax,&xxmin,&yymax,&yymin); grenzen(xb1[i], yb1[i],&xxmax,&xxmin,&yymax,&yymin); break; case tkreis: case tkreisgef: ellpar(i,&xm,&ym,&lx,&ly,&cr,&sr); initgrenzen(xm+lx, ym+ly,&xxmax,&xxmin,&yymax,&yymin); grenzen(xm-lx, ym-ly,&xxmax,&xxmin,&yymax,&yymin); break; case tell: case tellgef: initgrenzen(x1[i],y1_[i],&xxmax,&xxmin,&yymax,&yymin); ellgrenzpunkte(i,&xxmax,&xxmin,&yymax,&yymin); break; case tkreisbogen: case tellbogen: initgrenzen(xb1[i], yb1[i],&xxmax,&xxmin,&yymax,&yymin); grenzen(xb2[i],yb2[i],&xxmax,&xxmin,&yymax,&yymin); ellgrenzpunkte(i,&xxmax,&xxmin,&yymax,&yymin); break; case tellsektorgef: case tkreissektorgef: initgrenzen(x1[i],y1_[i],&xxmax,&xxmin,&yymax,&yymin); grenzen(xb1[i], yb1[i],&xxmax,&xxmin,&yymax,&yymin); grenzen(xb2[i],yb2[i],&xxmax,&xxmin,&yymax,&yymin); ellgrenzpunkte(i,&xxmax,&xxmin,&yymax,&yymin); break; case tbezier: case tbeziergef: /* keine minmax-Berechnung, da diese ueber ausel() erfolgt */ return; }/*case*/ elxmin[i]=xxmin; elxmax[i]=xxmax; elymin[i]=yymin; elymax[i]=yymax; } Static Void ausfastalles() { static void ausnurelemente(); XClearWindow(display,win); if (erwartet==tastatur_erwartet) textpositionieren(); prompt(); ausmenue(); ausnurelemente(); } Static Void ausalles() { static void auselemente(); XClearWindow(display,win); if (erwartet==tastatur_erwartet) textpositionieren(); prompt(); ausmenue(); auselemente(); ausalleclickmarken(); if (erwartet==tastatur_erwartet) cursan(curs_x,curs_y); } Static Void verschieben(art) long art; { double f, fminus, fplus, dxx, dyy, xmax, ymax, xmin, ymin; Char s1[maxstrl+1], s2[maxstrl+1], s3[maxstrl+1], s4[maxstrl+1], s5[maxstrl+1], s6[maxstrl+1]; fplus = 1.5; fminus = 1.0 / fplus; strcpy(s1, pr1); strcpy(s2, pr2); strcpy(s3, pr3); strcpy(s4, pr4); strcpy(s5, pr5); strcpy(s6, pr6); strcpy(pr1, pr2menue[art]); strcpy(pr2, nullstr); strcpy(pr3, nullstr); strcpy(pr4, nullstr); strcpy(pr5, nullstr); strcpy(pr6, nullstr); prompt(); f = 1.0; dxx = (long)floor((xzmax - xgr) / 4.0 + 0.5); dyy = (long)floor(yzmax / 4.0 + 0.5); switch (art) { case mlschieben: dyy = 0.0; dxx = -dxx; break; case mrschieben: dyy = 0.0; break; case moschieben: dxx = 0.0; break; case muschieben: dxx = 0.0; dyy = -dyy; break; case mgross: dxx = 0.0; dyy = 0.0; f = fplus; break; case mklein: dxx = 0.0; dyy = 0.0; f = fminus; break; case mcenter: minmax(&xmin, &xmax, &ymin, &ymax); dxx = xmittelzei - (long)floor((xmax + xmin) * 0.5 + 0.5); dyy = ymittelzei - (long)floor((ymax + ymin) * 0.5 + 0.5); break; }/*case*/ elskalieren(&gridw, dxx, dyy, f); XClearWindow(display,win); selmenue[art] = false; strcpy(pr1, s1); strcpy(pr2, s2); strcpy(pr3, s3); strcpy(pr4, s4); strcpy(pr5, s5); strcpy(pr6, s6); ausalles(); } /*schieben*/ Static Void sondertaste (taste) long taste; {/* Behandlung von Tasten, die nicht bei */ /* erwarteter Texteingabe gedrueckt wurden */ if ((taste == tastecursleft1)||(taste == tastecursleft2)) verschieben((long)mlschieben); if ((taste == tastecursright1)||(taste == tastecursright2)) verschieben((long)mrschieben); if ((taste == tastecursup1)||(taste == tastecursup2)) verschieben((long)moschieben); if ((taste == tastecursdown1)||(taste == tastecursdown2)) verschieben((long)muschieben); if ((taste == tasteplus2)||(taste == tasteplus1)) verschieben((long)mgross); if ((taste == tasteminus2)||(taste == tasteminus1)) verschieben((long)mklein); } Static Void control (taste, press) long taste, press; { if ((taste == tastecontroll)||(taste == tastecontrolr)) controlan = press; } Static Void menueloc(x, y, i) double x, y; long *i; { long j; *i = 0; for (j = 1; j <= zmenue; j++) { if (x < xam[j]) goto _L1; if (x > xem[j]) goto _L1; if (y < yam[j]) goto _L1; if (y > yem[j]) goto _L1; *i = j; goto _L2; _L1: ; } goto _L3; _L2: if (*i==mredraw) { *i=0; ausalles(); return; } /* test ob Anklicken fuer changeattributs relevant */ if (*i==mpfeilanf) changelende = true; if (*i==mpfeilende) changelende = true; if (*i==mcapprojecting) changelende = true; if (*i==mdick) changelwidth = true; if (*i==mgestrichelt) changelstyle = true; if (*i==mgepunktet) changelstyle = true; if (*i==mfont) changefont = true; if (*i==mcolor) changecolor = true; if (*i==mltext) changeposition = true; if (*i==mrtext) changeposition = true; if (*i==mbtext) changeposition = true; if (*i==mttext) changeposition = true; if (!(radiogroup[*i] == 1 && selmenue[*i]==true)) { if (selmenue[*i]==true) selmenue[*i] = false; else selmenue[*i]=true; ausmenueelement(*i); } if (radiogroup[*i] != 0 && selmenue[*i]==true) { /*if*/ for (j = 1; j <= zmenue; j++) { if (*i != j && selmenue[j]==true && radiogroup[j] == radiogroup[*i]) { selmenue[j] = false; ausmenueelement(j); } } /*j*/ } _L3: ; } Static boolean gschnittpunkt(x1, y1, dx1, dy1, x2, y2, dx2, dy2, xs, ys) double x1, y1, dx1, dy1, x2, y2, dx2, dy2, *xs, *ys; { boolean Result; double xp, yp, m1, m2, dm, diffx12, diffy12; /*Schnittpunkt zweier Geraden*/ Result = false; diffx12 = x1 - x2; diffy12 = y1 - y2; xp = 0.0; yp = 0.0; if (dx1 == 0.0 && dx2 == 0.0) /*parallel*/ goto _L2; if (dx1 == 0.0) { xp = x1; yp = dy2 / dx2 * diffx12 + y2; goto _L1; } if (dx2 == 0.0) { xp = x2; yp = y1 - dy1 / dx1 * diffx12; goto _L1; } if (dy1 == 0.0 && dy2 == 0.0) /*parallel*/ goto _L2; if (dy1 == 0.0) { xp = diffy12 * dx2 / dy2 + x2; yp = y1; goto _L1; } if (dy2 == 0.0) { xp = x1 - diffy12 * dx1 / dy1; yp = y2; goto _L1; } m1 = dy1 / dx1; m2 = dy2 / dx2; if (si_fabs(m1 - m2) < 0.0001) /*parallel*/ goto _L2; dm = m2 - m1; dm = 1 / dm; xp = diffy12 * dm + m2 * dm * x2 - m1 * dm * x1; yp = m2 * dm * y1 - m1 * dm * m2 * diffx12 - m1 * dm * y2; _L1: Result = true; _L2: *xs = xp; *ys = yp; return Result; } Static boolean lot(x1, y1, dx1, dy1, xp, yp, xs, ys) double x1, y1, dx1, dy1, xp, yp, *xs, *ys; { if (gschnittpunkt(x1, y1, dx1, dy1, xp, yp, -dy1, dx1, xs, ys)==true) return true; else return false; } Static boolean inxystrecke(x1, y1, x2, y2, xs, ys) double x1, y1, x2, y2, xs, ys; { double d, d1, d2; d = ppabstand(x1, y1, x2, y2); d1 = ppabstand(xs, ys, x1, y1); d2 = ppabstand(xs, ys, x2, y2); if ((d1 + d2) < (d + 3.0)) return true; else return false; } Static double pgxyabstand(x1, y1, x2, y2, xp, yp) double x1, y1, x2, y2, xp, yp; { double xs,ys,d12,d1s,d2s,dmin; dmin = initabstand; lot(x1, y1, x2-x1, y2-y1, xp, yp, &xs, &ys); d12=ppabstand(x1,y1,x2,y2); d1s=ppabstand(x1,y1,xs,ys); d2s=ppabstand(x2,y2,xs,ys); if (inxystrecke(x1, y1, x2, y2, xs, ys)==true) { /* Fusspunkt Lot ist etwa in Strecke */ /* nur dann wird Strecke als selektiert betrachtet! */ dmin = ppabstand(xp,yp,xs,ys); } return dmin; } Static double pgabstand(elsel, xp, yp) long elsel; double xp, yp; { double dmin; dmin = pgxyabstand(x1[elsel], y1_[elsel], x2[elsel], y2[elsel], xp, yp); return dmin; } Static Void kopunvotext(elsel, i) long elsel, i; { typ[i] = typ[elsel]; x1[i] = x1[elsel]; y1_[i] = y1_[elsel]; x2[i] = x2[elsel]; y2[i] = y2[elsel]; xb1[i] = xb1[elsel]; yb1[i] = yb1[elsel]; xb2[i] = xb2[elsel]; yb2[i] = yb2[elsel]; wanf[i] = wanf[elsel]; wend[i] = wend[elsel]; elxmin[i] =elxmin[elsel]; elxmax[i] =elxmax[elsel]; elymin[i] =elymin[elsel]; elymax[i] =elymax[elsel]; lineende[i] = lineende[elsel]; linedicke[i] = linedicke[elsel]; linetype[i] = linetype[elsel]; laenge1[i] = laenge1[elsel]; laenge2[i] = laenge2[elsel]; rotwi[i] = rotwi[elsel]; crw[i] = crw[elsel]; srw[i] = srw[elsel]; textno[i] = textno[elsel]; sequenz[i] = sequenz[elsel]; blink[i] = false; /* Beim Kopieren ist neues Element nicht */ /* selektiert !!!!! */ blinkalt[i] = false; group[i] = group[elsel]; } Static Void loescheelement(i) long i; { if ((typ[i] == ttext) || (typ[i] == -ttext)) strcpy(texte[textno[i]],nullstr); typ[i] = 0; } Static Void kompakt() { /*belegte Elemente an Anfang der Liste*/ /*ohne Aenderung der Reihenfolge */ long i, delta; delta=0; for (i = 1; i <= zelmax; i++) { if (typ[i] <= 0) { delta++; loescheelement(i); } else { if (delta != 0) {kopunvotext(i,i-delta); typ[i]=0;} } } zelmax=zelmax-delta; } Static Void freieselement(k) long *k; { long i; _L0: if (zelmax==zel) fehler(1L); zelmax++; i = zelmax; *k = i; typ[i] = -1; /*vorlaeufig belegt*/ x1[i] = 0.0; y1_[i] = 0.0; x2[i] = 0.0; y2[i] = 0.0; xb1[i] = 0.0; yb1[i] = 0.0; xb2[i] = 0.0; yb2[i] = 0.0; wanf[i] = 0.0; wend[i] = wg; elxmin[i] = 0.0; elxmax[i] = 0.0; elymin[i] = 0.0; elymax[i] = 0.0; linedicke[i] = 1L; lineende[i] = 0L; linetype[i] = 1L; laenge1[i] = 0.0; laenge2[i] = 0.0; rotwi[i] = 0.0; crw[i] = 1.0; srw[i] = 0.0; textno[i] = 0; sequenz[i] = 0; blink[i] = false; blinkalt[i] = false; group[i] = 0; } Static Void freiestextel(k) long *k; { long i; for (i = 1; i <= zstr; i++) { if (istnullstr(texte[i])==true) goto _L1; } fehler(2L); _L1: *k = i; } Static Void kopunv(elsel, i) long elsel, i; { kopunvotext(elsel,i); if (typ[i] != ttext) return; typ[i] = -ttext; freiestextel(&textno[i]); typ[i] = ttext; strcpy(texte[textno[i]], texte[textno[elsel]]); } Static Void ausline(k,zcolor) long k,zcolor; { rpxarray[0]=x1[k]; rpyarray[0]=y1_[k]; rpxarray[1]=x2[k]; rpyarray[1]=y2[k]; auspolyline(zcolor,k,2L); } Static Void ausgefviereck(k,zcolor) long k,zcolor; { rpxarray[0]=x1[k]; rpyarray[0]=y1_[k]; rpxarray[1]=xb1[k]; rpyarray[1]=yb1[k]; rpxarray[2]=x2[k]; rpyarray[2]=y2[k]; rpxarray[3]=xb2[k]; rpyarray[3]=yb2[k]; rpxarray[4]=x1[k]; rpyarray[4]=y1_[k]; ausfillpolygon(5L,zcolor); } Static Void ausgefdreieck(k,zcolor) long k,zcolor; { rpxarray[0]=x1[k]; rpyarray[0]=y1_[k]; rpxarray[1]=x2[k]; rpyarray[1]=y2[k]; rpxarray[2]=xb1[k]; rpyarray[2]=yb1[k]; rpxarray[3]=x1[k]; rpyarray[3]=y1_[k]; ausfillpolygon(4L,zcolor); } Static Void austextline(k,zcolor) long k; { long ix1,iy1,ix2,iy2; welt_to_bildschirm(xb1[k], yb1[k], &ix1, &iy1); welt_to_bildschirm(xb2[k], yb2[k], &ix2, &iy2); setvalues(display,gczeichnung,zcolor,6L,0L,0L); XDrawLine(display,win,gczeichnung,ix1,iy1,ix2,iy2); } Static Void bogenauspar(elsel,ltyp,ldicke,lende,lcolor, ixa,iya,ilx,ily,iwa,idw) long elsel,*ltyp,*ldicke,*lcolor,*ixa,*iya,*ilx,*ily,*iwa,*idw; { double xm,ym,lx,ly,cr,sr,wa,dw; long ixm, iym; ellpar(elsel, &xm, &ym, &lx, &ly, &cr, &sr); getlineattribute(elsel, typ[elsel], ltyp, ldicke, lende, lcolor); welt_to_bildschirm(xm-lx, ym+ly, ixa, iya); *ilx = siintround(2.0*lx); *ily = siintround(2.0*ly); wa=wanf[elsel]; dw=wend[elsel]-wa; if (dw<=0.0) dw += wg; /* Winkel in Grad*64 */ *iwa=siintround(wa*6.4); *idw=siintround(dw*6.4); } Static Void ausbogen(elsel,zcolor) long elsel,zcolor; { long ltyp,ldicke,lende,lcolor,ixa,iya,ilx,ily,iwa,idw; bogenauspar(elsel,<yp,&ldicke,&lende,&lcolor, &ixa,&iya,&ilx,&ily,&iwa,&idw); setvalues(display,gczeichnung,zcolor,ltyp,ldicke,lende); XDrawArc(display,win,gczeichnung,ixa,iya,ilx,ily,iwa,idw); winpfeile(elsel,zcolor); } Static Void ausgefbogen(elsel,zcolor) long elsel,zcolor; { long ltyp,ldicke,lende,lcolor,ixa,iya,ilx,ily,iwa,idw; bogenauspar(elsel,<yp,&ldicke,&lende,&lcolor, &ixa,&iya,&ilx,&ily,&iwa,&idw); setvalues(display,gczeichnung,zcolor,ltyp,ldicke,lende); XFillArc(display,win,gczeichnung,ixa,iya,ilx,ily,iwa,idw); winpfeile(elsel,zcolor); } Static Void ellipse2polygon(i,kerg) long i,*kerg; { double umfang, lambda, lambdaq, xp, yp, dw, w, xm, ym, lx, ly, lmax, cr, sr, wa, we; long k, m; ellpar(i, &xm, &ym, &lx, &ly, &cr, &sr); lambda = (lx-ly)/(lx+ly); lambdaq = lambda*lambda; umfang = pi*(lx+ly)*(64.0-3.0*lambdaq*lambdaq)/(64.0-16*lambdaq); m = umfang/10.0; /* ungefaehre Zahl der Strecken mit je 5 Pixel */ if (m < 10) m = 10; if (m > maxpunkte) m = maxpunkte - 10; if (m > 50) m = 50; dw = wg/m; wa = wanf[i]; we = wend[i]; w = wa; if (we <= wa) we += wg; k = 0; while (w < we){ ellw_xy(xm, ym, lx, ly, cr, sr, w, &xp, &yp); w += dw; rpxarray[k]=xp; rpyarray[k]=yp; k++; }; ellw_xy(xm, ym, lx, ly, cr, sr, we, &xp, &yp); rpxarray[k]=xp; rpyarray[k]=yp; k++; if (typ[i] == tellsektorgef) { rpxarray[k]=xm; rpyarray[k]=ym; k++; rpxarray[k]=rpxarray[0]; rpyarray[k]=rpyarray[0]; k++; } *kerg = k; } Static Void ausellgef(i,zcolor) long i,zcolor; { long k; ellipse2polygon(i,&k); ausfillpolygon(k,zcolor); } Static Void ausellipse(i,zcolor) long i,zcolor; { long k; ellipse2polygon(i,&k); auspolyline(zcolor,i,k); } Static Void ausel(i, painterase) long i, painterase; { long fontart, zcolor; zcolor = getzcolor(i, painterase); /* zcolor ist Farbe der Zeichnung */ /* bestimmen aus Angabe color und Wert Farbe bei Element! */ switch (typ[i]) { /*case*/ case ttext: if (rotwi[i] != 0.0) austextline(i,zcolor); fontart=linetype[i]; if (i != texterase) ztextaus(win, i, x2[i], y2[i], texte[textno[i]],zcolor,fontart); setzetextmarke(x1[i], y1_[i], zcolor); break; case tgerade: ausline(i,zcolor); break; case trechteckgef: case tviereckgef: ausgefviereck(i,zcolor); break; case tdreieckgef: ausgefdreieck(i,zcolor); break; case tkreis: ausbogen(i,zcolor); break; case tkreisgef: case tkreissektorgef: ausgefbogen(i,zcolor); break; case tkreisbogen: ausbogen(i,zcolor); break; case tellgef: case tellsektorgef: ausellgef(i,zcolor); break; case tell: case tellbogen: ausellipse(i,zcolor); break; case tbezier: ausbezier(i,zcolor); break; case tbeziergef: ausbeziergef(i,zcolor); break; } } Static Void ltd_usleep(s, mu) long s, mu; { st_delay.tv_usec = mu; st_delay.tv_sec = s; select(32, 0, 0, 0, &st_delay); } Static Void Flush_ltd_usleep(s, mu) long s, mu; { XFlush(display); /* ganz wichtig, damit vor sleep noch alles ausgegeben wird */ ltd_usleep(s, mu); } Static Void ausblinkelemente() { long i,f; f = 1; if (tablett) f = 10; if (blinkintervallzaehler==0) { /* blinkfarbe == paint oder erase ! */ if (blinkfarbe == erase) { for (i = 1; i <= zelmax; i++) if ((typ[i] > 0)&&(blink[i]==true)) ausel(i, erase); for (i = 1; i <= zelmax; i++) if ((typ[i] > 0)&&(blink[i]==false)) ausel(i, paint); } else for (i = 1; i <= zelmax; i++) { if (typ[i] > 0) ausel(i, paint); } } ausgrid(schwarz); Flush_ltd_usleep(0L,(long)(100000/f)); /* 100/f ms Grund-Wartezeit bzw. Reaktionszeit */ if ((blinkfarbe==paint)&&(blinkintervallzaehler++ > 10*f)) { blinkintervallzaehler = 0; blinkfarbe=erase; } else { if ((blinkfarbe==erase)&&(blinkintervallzaehler++ > 2*f)) { blinkintervallzaehler = 0; blinkfarbe=paint; } } } Static Void ausnurelemente() { long i; for (i = 1; i <= zelmax; i++) { if (typ[i] > 0) ausel(i, paint); } /* end for */ zeichnen = false; } Static Void auselemente() { ausnurelemente(); ausalleclickmarken(); ausgrid(schwarz); } Static Void blinkenaus() { blinkend = false; auselemente(); } Static Void blinkenan() { long i; for (i = 1; i <= zelmax; i++) { blinkalt[i] = blink[i]; blink[i] = false; } if (blinkend==true) blinkenaus(); blinkfarbe = erase; blinkend = true; blinkintervallzaehler = 0; } Static boolean duplikat(); Static long interncreateline(elselalt, xx1, yy1, xx2, yy2) long elselalt; double xx1, yy1, xx2, yy2; { double d; long elsel, ldicke, ltyp, lende; if (elselalt == 0) { d = ppabstand(xx1, yy1, xx2, yy2); if (d < dminein) return 0; } freieselement(&elsel); typ[elsel] = tgerade; x1[elsel] = xx1; y1_[elsel] = yy1; x2[elsel] = xx2; y2[elsel] = yy2; setlineattribute(elselalt, elsel); berechneminmax(elsel); return elsel; } Static Void createline(elselalt, xx1, yy1, xx2, yy2) long elselalt; double xx1, yy1, xx2, yy2; { long elsel; elsel = interncreateline(elselalt, xx1, yy1, xx2, yy2); if (elsel != 0) ausel(elsel, paint); } Static long einbezier(x,y,taste,msel,phase) long *msel,phase,taste; double x,y; { static long elsel; long elselalt, ltyp, ldicke, lende; static boolean fortsetzung; double d1,d2; switch (phase){ case 0: goto L0; case 1: goto L1; case 2: goto L2; case 3: goto L3; case 4: goto L4; } L0: fortsetzung = false; return 1; L1: freieselement(&elsel); x1[elsel] = x; y1_[elsel] = y; strcpy(pr4, " end point of tangent to starting point?"); return 2; L2: xb1[elsel] = x; yb1[elsel] = y; if (si_fabs(x - x1[elsel]) < 3.0 && si_fabs(y - y1_[elsel]) < 3.0) return 2; strcpy(pr4, " first point of tangent to end point?"); return 3; L3: xb2[elsel] = x; yb2[elsel] = y; if (fortsetzung == true) { /* Steigung bei Anfangspunkt beibehalten, aber die Entfernung zum */ /* Punkt 2 auf halben Abstand Punkt3 von Anfangspunkt setzen */ d1 = ppabstand(x1[elsel],y1_[elsel], xb1[elsel],yb1[elsel]); d2 = ppabstand(x1[elsel],y1_[elsel], x,y); if (d2==0.0) d2=4.0; xb1[elsel] = x1[elsel] + d2/d1*0.4*(xb1[elsel]-x1[elsel]); yb1[elsel] = y1_[elsel] + d2/d1*0.4*(yb1[elsel]-y1_[elsel]); } strcpy(pr4, pr3menue[*msel]); return 4; L4: x2[elsel] = x; y2[elsel] = y; if (si_fabs(x - xb2[elsel]) < 3.0 && si_fabs(y - yb2[elsel]) < 3.0) return 4; if (selmenue[mgefuellt] == true) typ[elsel] = tbeziergef; else typ[elsel] = tbezier; setlineattribute(0L, elsel); /* berechneminmax(elsel); */ /* unnoetig, da bei ausel fuer bezier berechnet!! */ ausel(elsel, paint); /* ggf. weiterfuehren der Bezierkurve */ elselalt=elsel; freieselement(&elsel); x1[elsel]=x2[elselalt]; y1_[elsel]=y2[elselalt]; xb1[elsel]=2*x1[elsel]-xb2[elselalt]; yb1[elsel]=2*y1_[elsel]-yb2[elselalt]; strcpy(pr4, " first point of tangent to end point?"); fortsetzung = true; return 3; } Static Void ellanfendpunkt(i) long i; { double lx, ly, xm, ym, cr, sr; ellpar(i, &xm, &ym, &lx, &ly, &cr, &sr); while (wanf[i] >= wg) wanf[i] -= wg; while (wanf[i] < 0.0) wanf[i] += wg; while (wend[i] > wg) wend[i] -= wg; while (wend[i] < 0.0) wend[i] += wg; ellw_xy(xm, ym, lx, ly, cr, sr, wanf[i], &xb1[i], &yb1[i]); ellw_xy(xm, ym, lx, ly, cr, sr, wend[i], &xb2[i], &yb2[i]); } Static Void kreisanfendpunkt(i) long i; { double xm, ym, rad; xm = x1[i]; ym = y1_[i]; rad = laenge1[i]; while (wanf[i] >= wg) wanf[i] -= wg; while (wanf[i] < 0.0) wanf[i] += wg; while (wend[i] > wg) wend[i] -= wg; while (wend[i] < 0.0) wend[i] += wg; xb1[i] = xm + rad * cos(wanf[i] * fgradbo); yb1[i] = ym + rad * sin(wanf[i] * fgradbo); xb2[i] = xm + rad * cos(wend[i] * fgradbo); yb2[i] = ym + rad * sin(wend[i] * fgradbo); } Static long winkeleingabe(w) double *w; { long i; double wi; if(istnullstr(EinText)==true) return 1; i=sscanf(EinText,"%lf",&wi); if (i!=1) return 2; if ((wi > 4000)||(wi < -4000)) return 2; while (wi > 360.0) wi -= 360.0; while (wi < 0.0) wi += 360.0; *w = wi*10; return 0; } Static long einarc(x,y,elsel,taste,phase) long elsel, taste, phase; double x,y; /* Eingabe Kreisbogen */ { long i, ltyp, ldicke, lende; phase -= phase2; switch (phase){ case 0: goto L0; case 1: goto L1; case 2: goto L2; } L0: strcpy(pr4, pranfwi); if (selmenue[mdegrees]==true) inittastaturtext(nullstr,pr2menue[mdegrees],1L); winerwartet = 1; return (phase2+1); L1: if (taste==0) {/* stringeingabe*/ i = winkeleingabe(&wanf[elsel]); if (i != 0) goto L0; } else wanf[elsel] = winkelk(x1[elsel], y1_[elsel], x, y); L1B: winerwartet = 1; strcpy(pr4, prendwi); if (selmenue[mdegrees]==true) inittastaturtext(nullstr,pr2menue[mdegrees],1L); return (phase2+2); L2: if (taste==0) {/* stringeingabe*/ i = winkeleingabe(&wend[elsel]); if (i != 0) goto L1B; } else wend[elsel] = winkelk(x1[elsel], y1_[elsel], x, y); winerwartet = 0; if (si_fabs(wanf[elsel]-wend[elsel])<10) goto L1B; setlineattribute(0L, elsel); kreisanfendpunkt(elsel); if (selmenue[mgefuellt]==true) {typ[elsel] = tkreissektorgef;} else typ[elsel] = tkreisbogen; berechneminmax(elsel); ausel(elsel, paint); if (typ[elsel] != tkreissektorgef) return 0; /* anschliessenden Sektor eingeben, nur Endwinkel */ /* zunaechst bisherigen Sektor umspeichern */ freieselement(&i); kopunv(elsel,i); typ[elsel] = -1; wanf[elsel] = wend[elsel]; strcpy(pr4, prendwisektor); goto L1B; } Static Void normgrid() { double a, dx, dy; dx = gridwx1 + gridwx2; dy = gridwy1 + gridwy2; a = sifsqrt(1.0, dx * dx + dy * dy); gridw0 = a; gridw = a; a = 1 / a; gridwx1 *= a; gridwy1 *= a; gridwx2 *= a; gridwy2 *= a; } Static Void selmenloeschen(msel) long *msel; { selmenue[*msel]=false; ausmenueelement(*msel); *msel=0; } Static long eingitter(x,y,msel,phase) long *msel,phase; double x,y; /*eingitter*/ { double dx, dy, a, c, aq, cq, cosa; static double b, bq; switch (phase){ case 0: goto L0; case 1: goto L1; case 2: goto L2; case 3: goto L3; } L0: strcpy(pr2, " grid"); ausgrid(weiss); initgrid(); ausgrid(schwarz); strcpy(pr4, pr2menue[*msel]); return 1; L1: ausgrid(weiss); gridx0 = x; gridy0 = y; ausgrid(schwarz); strcpy(pr4, " first grid point to the right?"); return 2; L2: x -= gridx0; y -= gridy0; bq = x * x + y * y; b = sifsqrt(1.0, bq); if (b < 5) return 2; ausgrid(weiss); gridwx1 = x; gridwy1 = y; gridwx2 = -y; gridwy2 = x; normgrid(); ausgrid(schwarz); strcpy(pr4, " first grid point up?"); return 3; L3: x -= gridx0; y -= gridy0; cq = x * x + y * y; c = sifsqrt(1.0, cq); if (c < 5) return 3; dx = gridwx1 * gridw - x; dy = gridwy1 * gridw - y; aq = dx * dx + dy * dy; a = sifsqrt(1.0, aq); if (a < 5) return 3; /*Kosinussatz*/ cosa = (aq - bq - cq) / (2 * b * c); if (si_fabs(cosa) > 0.98) return 2; ausgrid(weiss); gridwx1 *= gridw; gridwy1 *= gridw; gridwx2 = x; gridwy2 = y; normgrid(); ausgrid(schwarz); selmenloeschen(msel); return 0; } Static long eincircle(x,y,taste,msel,phase) long *msel,taste,phase; double x,y; /* Eingabe Kreis oder Kreisbogen */ { static long elsel; long ltyp, ldicke, lende; switch (phase){ case 0: goto L0; case 1: goto L1; case 2: goto L2; default: goto L3; /* Fuer einarc */ } L0: return 1; L1: freieselement(&elsel); x1[elsel] = x; y1_[elsel] = y; strcpy(pr4, pr3menue[*msel]); return 2; L2: laenge1[elsel] = ppabstand(x, y, x1[elsel], y1_[elsel]); if (laenge1[elsel] < 2.0) laenge1[elsel] = 2.0; laenge2[elsel] = laenge1[elsel]; setlineattribute(0L, elsel); lineende[elsel] = 0; if ((selmenue[mbogen]!=true)&&(selmenue[mgefuellt]!=true)) { typ[elsel] = tkreis; berechneminmax(elsel); ausel(elsel, paint); return 0; } if ((selmenue[mbogen]!=true)&&(selmenue[mgefuellt]==true)) { typ[elsel] = tkreisgef; berechneminmax(elsel); ausel(elsel, paint); return 0; } phase=phase2; L3: phase =einarc(x,y,elsel,taste,phase); return phase; } Static boolean relevant(i, xp, yp) long i; double xp, yp; /* Pruefung, ob der Punkt relevant fuer */ /* die Wahl des Elements i sein kann */ { double xanf, yanf, xend, yend, rmax; if (typ[i] <=0) return false; rmax = 1.05*maxabstand; xanf=elxmin[i]-rmax; xend=elxmax[i]+rmax; yanf=elymin[i]-rmax; yend=elymax[i]+rmax; if ((xp >= xanf)&&(xp <= xend)&& (yp >= yanf)&&(yp <= yend)) return true; return false; } Static double pkreisabstand(i, xp, yp) long i; double xp, yp; { double d, dmin; dmin= initabstand; d = si_fabs(ppabstand(x1[i], y1_[i], xp, yp) - laenge1[i]); if (d < dmin) dmin = d; return dmin; } Static double pkreisboabstand(i, xp, yp) long i; double xp, yp; { double d, w; d = pkreisabstand(i, xp, yp); if (d>=initabstand) return d; w = winkelk(x1[i], y1_[i], xp, yp); if (inwinkel(i, w)==false) return initabstand; return d; } Static double pellabstand(i, xp, yp) long i; double xp, yp; { double xell, yell, w, d, dmin; dmin= initabstand; w = winkelell(x1[i], y1_[i], laenge1[i], laenge2[i], crw[i], srw[i], xp, yp); ellw_xy(x1[i], y1_[i], laenge1[i], laenge2[i], crw[i], srw[i], w, &xell, &yell); d = ppabstand(xp, yp, xell, yell); if (d < dmin) dmin = d; return dmin; } Static double pellboabstand(i, xp, yp) long i; double xp, yp; { double xell, yell, w, d, dmin; dmin= initabstand; w = winkelell(x1[i], y1_[i], laenge1[i], laenge2[i], crw[i], srw[i], xp, yp); ellw_xy(x1[i], y1_[i], laenge1[i], laenge2[i], crw[i], srw[i], w, &xell, &yell); d = ppabstand(xp, yp, xell, yell); if (inwinkel(i, w)==false) return dmin; if (d < dmin) dmin = d; return dmin; } Static double pviereckabstand(i, xp, yp) long i; double xp, yp; { double d, dmin; dmin = pgxyabstand(x1[i], y1_[i], x2[i], y2[i], xp, yp); d = pgxyabstand(x1[i], y1_[i], xb1[i], yb1[i], xp, yp); if (d < dmin) dmin = d; d = pgxyabstand(xb1[i], yb1[i], x2[i], y2[i], xp, yp); if (d < dmin) dmin = d; d = pgxyabstand(x2[i], y2[i], xb2[i], yb2[i], xp, yp); if (d < dmin) dmin = d; d = pgxyabstand(xb2[i], yb2[i], x1[i], y1_[i], xp, yp); if (d < dmin) dmin = d; return dmin; } Static double pdreieckabstand(i, xp, yp) long i; double xp, yp; { double d, dmin; dmin = pgxyabstand(x1[i], y1_[i], xb1[i], yb1[i], xp, yp); d = pgxyabstand(xb1[i], yb1[i], x2[i], y2[i], xp, yp); if (d < dmin) dmin = d; d = pgxyabstand(x2[i], y2[i], x1[i], y1_[i], xp, yp); if (d < dmin) dmin = d; return dmin; } Static double abstmod1(d) double d; {/* fuer nicht gefuellte Elemente */ double x, dgrenz; dgrenz = maxabstand*0.3; if (d < dgrenz) return d; x = (d-dgrenz)*2.0+dgrenz; return x; } Static double abstmod2(d) double d; {/* fuer gefuellte Elemente */ double x, dgrenz; dgrenz = maxabstand*0.3; if (d < dgrenz) return (d+2.0); x = (d-dgrenz)*0.5+dgrenz+2.0; return x; } Static double abstelement(i, xp, yp) long i; double xp, yp; /* wird nur zur Selektion der Elemente benutzt, deshalb wird der */ /* berechnete Abstand bei gefuellten Elementen und anderen Elementen */ /* so modifiziert, dass bei gef. Elemeneten groessere Abstaende noch */ /* zugelassen sind und kleinere Abstaende erhoeht werden */ /* In der Naehe eines nichtgefuellten Element wird deshalb diese bevorzugt */ { double d, d2; d = initabstand; if (typ[i] <= 0) goto _L1; if (relevant(i, xp, yp)==false) goto _L1; switch (typ[i]) { case ttext: d = ppabstand(x1[i], y1_[i], xp, yp); goto Lngef; case tgerade: d = pgabstand(i, xp, yp); goto Lngef; case trechteckgef: case tviereckgef: d = pviereckabstand(i, xp, yp); goto Lgef; case tdreieckgef: d = pdreieckabstand(i, xp, yp); goto Lgef; case tkreis: d = pkreisabstand(i, xp, yp); goto Lngef; case tkreisgef: d = pkreisabstand(i, xp, yp); goto Lgef; case tkreisbogen: d = pkreisboabstand(i, xp, yp); goto Lngef; case tkreissektorgef: d = pkreisboabstand(i, xp, yp); d2 = pgxyabstand(x1[i], y1_[i], xb2[i], yb2[i], xp, yp); if (d2 < d) d = d2; d2 = pgxyabstand(x1[i], y1_[i], xb1[i], yb1[i], xp, yp); if (d2 < d) d = d2; goto Lgef; case tell: d = pellabstand(i, xp, yp); goto Lngef; case tellgef: d = pellabstand(i, xp, yp); goto Lgef; case tellbogen: d = pellboabstand(i, xp, yp); goto Lngef; case tellsektorgef: d = pellboabstand(i, xp, yp); d2 = pgxyabstand(x1[i], y1_[i], xb2[i], yb2[i], xp, yp); if (d2 < d) d = d2; d2 = pgxyabstand(x1[i], y1_[i], xb1[i], yb1[i], xp, yp); if (d2 < d) d = d2; goto Lgef; case tbezier: d = pbezabstand(i, xp, yp); goto Lngef; case tbeziergef: d = pbezabstand(i, xp, yp); d2 = pgxyabstand(x1[i], y1_[i], x2[i], y2[i], xp, yp); if (d2 < d) d = d2; goto Lgef; }/*case*/ Lgef: d = abstmod2(d); return d; Lngef: d= abstmod1(d); return d; _L1: return d; } Static Void sucheelement(art, elsel, xp, yp) long art, *elsel; double xp, yp; { double dmin, d; long i; *elsel = 0; dmin = 5.0*maxabstand; for (i = 1; i <= zelmax; i++) { if (typ[i] > 0) { if (suchtypok[typ[i]][art]=='y') { d = abstelement(i, xp, yp); if (d < dmin) { dmin = d; *elsel = i; } } } } } Static boolean blinkgruppeninre(); Static boolean elementinre(); Static boolean blinkelemente(xanf, yanf, xend, yend, elselmin) double xanf, yanf, xend, yend; long elselmin; {/* Alle Elemente/Gruppen im Bereich blink == true */ /* return true, falls solche vorhanden */ /* Falls Bereich: nur Elemente >= elselmin beruecksichtigt */ /* Blinken ist aber noch nicht aktiviert !! */ long elsel, erg; blinkenan(); blinkend = false; initgruppentag(false); if (xanf == xend) { /*selecteinelement*/ sucheelement((long)alleelem, &elsel, xanf, yanf); if (elsel == 0) { return false; } if (selmenue[mgroupmode] == false){ blink[elsel] = true; return true; } blinkgruppe(elsel); return true; } if (selmenue[mgroupmode] == false){ erg = false; for (elsel = elselmin; elsel <= zelmax; elsel++) { if (elementinre(xanf, yanf, xend, yend, elsel)==true) { blink[elsel] = true; erg = true; } } return erg; } return blinkgruppeninre(xanf, yanf, xend, yend, elselmin); } Static long einellarc(x,y,elsel,taste,phase) long elsel,phase,taste; double x,y; /* Eingabe Ellipsenbogen */ { long i, ltyp, ldicke, lende; phase -= phase2; switch (phase){ case 0: goto L0; case 1: goto L1; case 2: goto L2; } L0: strcpy(pr4, pranfwi); if (selmenue[mdegrees]==true) inittastaturtext(nullstr,pr2menue[mdegrees],1L); winerwartet = 1; return (phase2+1); L1: if (taste==0) {/* stringeingabe*/ i = winkeleingabe(&wanf[elsel]); if (i != 0) goto L0; } else wanf[elsel] = winkelell(x1[elsel], y1_[elsel], laenge1[elsel], laenge2[elsel], crw[elsel], srw[elsel], x, y); L1B: winerwartet = 1; strcpy(pr4, prendwi); if (selmenue[mdegrees]==true) inittastaturtext(nullstr,pr2menue[mdegrees],1L); return (phase2+2); L2: if (taste==0) {/* stringeingabe*/ i = winkeleingabe(&wend[elsel]); if (i != 0) goto L1B; } else wend[elsel] = winkelell(x1[elsel], y1_[elsel], laenge1[elsel], laenge2[elsel], crw[elsel], srw[elsel], x, y); winerwartet = 0; if (si_fabs(wanf[elsel]-wend[elsel])<10) goto L1B; setlineattribute(0L, elsel); ellanfendpunkt(elsel); if (selmenue[mgefuellt]==true) {typ[elsel] = tellsektorgef;} else typ[elsel] = tellbogen; berechneminmax(elsel); ausel(elsel, paint); if (typ[elsel] != tellsektorgef) return 0; /* anschliessenden Sektor eingeben, nur Endwinkel */ /* zunaechst bisherigen Sektor umspeichern */ freieselement(&i); kopunv(elsel,i); typ[elsel] = -1; wanf[elsel] = wend[elsel]; strcpy(pr4, prendwisektor); goto L1B; } Static long einellipse(x,y,xa,ya,taste,msel,phase) long *msel,taste,phase; double x,y,xa,ya; /* Eingabe Ellipse */ { double xpr_, ypr_; static long elsel, elselg; long ltyp, ldicke, lende; switch (phase){ case 0: goto L0; case 1: goto L1; case 2: goto L2; case 3: goto L3; case 4: goto L4; default: goto L5; /* Phasen in einellarc */ } L0: return 1; L1: freieselement(&elsel); x1[elsel] = x; y1_[elsel] = y; if (selmenue[mparallel]==true) { strcpy(pr4, " line, parallel to major axis? "); return 2; } strcpy(pr4, prxachse); return 3; L2: sucheelement((long)nurgerade, &elselg,xa, ya); if (elselg==0) return 2; setzewinkel(elsel, x1[elselg], y1_[elselg], x2[elselg], y2[elselg]); strcpy(pr4, prxachse); return 3; L3: xy_ell(x1[elsel], y1_[elsel], crw[elsel], srw[elsel], x, y, &xpr_, &ypr_); laenge1[elsel] = si_fabs(xpr_); if (laenge1[elsel] < dminein) return 3; strcpy(pr4, pryachse); return 4; L4: xy_ell(x1[elsel], y1_[elsel], crw[elsel], srw[elsel], x, y, &xpr_, &ypr_); laenge2[elsel] = si_fabs(ypr_); if (laenge2[elsel] < dminein) return 4; setlineattribute(0L, elsel); lineende[elsel] = 0; if ((selmenue[mbogen]!=true)&&(selmenue[mgefuellt]!=true)) { typ[elsel] = tell; berechneminmax(elsel); ausel(elsel, paint); return 0; } if ((selmenue[mbogen]!=true)&&(selmenue[mgefuellt]==true)) { typ[elsel] = tellgef; berechneminmax(elsel); ausel(elsel, paint); return 0; } phase=phase2; L5: return (einellarc(x,y,elsel,taste,phase)); } Static long einlinepp(x,y,xa,ya,elsel,taste,msel,phase) long *msel, elsel,taste,phase; double x,y,xa,ya; /* Endpunkt der Strecke durch Punkt gegeben */ { phase -= phase2; switch (phase){ case 0: goto L0; case 1: goto L1; } L0: strcpy(pr4, pr3menue[*msel]); return (phase2+1); L1: x2[elsel]=x; y2[elsel]=y; createline(0L, x1[elsel], y1_[elsel], x2[elsel], y2[elsel]); return 0; } Static long einlinepg(x,y,xa,ya,elsel,taste,msel,phase) long *msel, elsel,taste,phase; double x,y,xa,ya; /* Endpunkt durch parallele Linie */ { double dx, dy, dxu, dyu; long i; phase -= phase2; switch (phase){ case 0: goto L0; case 1: goto L1; case 2: goto L2; } L0: strcpy(pr4, pr2menue[mparallel]); return (phase2+1); L1: x2[elsel]=x; y2[elsel]=y; strcpy(pr4, pr3menue[mparallel]); return (phase2+2); L2: sucheelement((long)nurgerade, &i, xa, ya); if (i==0) return 2; dx = x2[i] - x1[i]; dy = y2[i] - y1_[i]; dxu = x2[elsel] - x1[elsel]; dyu = y2[elsel] - y1_[elsel]; if (si_fabs(dx) > si_fabs(dy)) { if (fsign(dxu)!=fsign(dx)){dx = -dx; dy = -dy;} } else { if (fsign(dyu)!=fsign(dy)){dx = -dx; dy = -dy;} } x2[elsel] = x1[elsel] + dx; y2[elsel] = y1_[elsel] + dy; createline(0L, x1[elsel], y1_[elsel], x2[elsel], y2[elsel]); return 0; } Static long einlinelot(x,y,xa,ya,elsel,taste,msel,phase) long *msel, elsel,taste,phase; double x,y,xa,ya; /* Endpunkt der Geraden durch Lot auf andere Gerade */ { double dx, dy, xs, ys; long i; phase -= phase2; switch (phase){ case 0: goto L0; case 1: goto L1; } L0: strcpy(pr4, pr3menue[mlot]); return (phase2+1); L1: sucheelement((long)nurgerade, &i, xa, ya); if (i==0) return (phase2+1); dx = x2[i] - x1[i]; dy = y2[i] - y1_[i]; if (lot(x1[i], y1_[i], dx, dy, x1[elsel], y1_[elsel], &xs, &ys)==true) createline(0L, x1[elsel], y1_[elsel], xs, ys); return 0; } Static long einline(x,y,xa,ya,taste,msel,phase) long *msel,taste,phase; double x,y,xa,ya; /* Eingabe einer Strecke */ { static long elsel, art; switch (phase){ case 0: goto L0; case 1: goto L1; default: goto L2; /* fuer einlinelot,einlinepg,einlinepp */ } L0: strcpy(pr4, pr2menue[*msel]); freieselement(&elsel); return 1; L1: /* erster Punkt */ x1[elsel]=x; y1_[elsel]=y; /*zweiter Punkt */ art=0; if (selmenue[mparallel]==true) art=1; if (selmenue[mlot]==true) art=2; phase=phase2; L2: switch (art){ case 0: phase=einlinepp(x,y,xa,ya,elsel,taste,msel,phase); break; case 1: phase=einlinepg(x,y,xa,ya,elsel,taste,msel,phase); break; case 2: phase=einlinelot(x,y,xa,ya,elsel,taste,msel,phase); break; } if (phase!=0) return phase; return 0; } /*line*/ Static Void ergbox(el1, el2) long el1, el2; { long i, j; double xx[4], yy[4]; xx[0] = x1[el1]; yy[0] = y1_[el1]; xx[1] = x2[el1]; yy[1] = y2[el1]; xx[2] = x1[el2]; yy[2] = y1_[el2]; xx[3] = x2[el2]; yy[3] = y2[el2]; for (i = 0; i <= 1; i++) { for (j = 2; j <= 3; j++) { if (si_fabs(xx[i] - xx[j]) < 5.0 && si_fabs(yy[i] - yy[j]) < 5.0) goto _L1; } } goto _L2; _L1: if (i == 0) { ftausch(&xx[0], &xx[1]); ftausch(&yy[0], &yy[1]); } if (j == 3) { ftausch(&xx[2], &xx[3]); ftausch(&yy[2], &yy[3]); } /* punkte 1 und 2 sind in der Naehe nun*/ createline(el2, xx[0], yy[0], xx[0] + xx[3] - xx[2], yy[0] + yy[3] - yy[2]); createline(el1, xx[3], yy[3], xx[3] + xx[0] - xx[1], yy[3] + yy[0] - yy[1]); _L2: ; } Static long geteingabezeile(datdeskr) FILE *datdeskr; { /* Zeile lesen, Zahl Zeichen zurueck, Grenze maxstrl */ long anz; if (fgets(eingabezeile,maxstrl+1,datdeskr)==NULL) anz = 1; else anz = strlen(eingabezeile); anz--; eingabezeile[anz] = '\0'; return anz; } Static Void eindateigruppen(datdeskr) FILE *datdeskr; { long i, erfolg, gruppe, element, vorg; /* den einzelnen Zeichnungselementen Gruppennummern zuordnen */ fscanf(datdeskr, "%ld", &gruppe); while ((gruppe > 0)&&(gruppe <= maxgruppen)) { fscanf(datdeskr, "%ld", &element); while ((element > 0)&&(element <= zelmax)) { if (typ[element]==0) fehler(11); if (group[element] != 0) fehler(12); group[element] = gruppe; fscanf(datdeskr, "%ld", &element); } if (element != 0) fehler(12); fscanf(datdeskr, "%ld", &gruppe); } if (gruppe != 0) fehler(13); /* Gruppenbaum aufbauen */ fscanf(datdeskr, "%ld%ld", &gruppe, &vorg); while ((gruppe > 0)&&(gruppe <= maxgruppen)) { if ((vorg <=0)||(vorg >maxgruppen)) fehler(15); if (vater[gruppe] != -1) fehler(15); /* Doppeldefinition */ vater[gruppe] = vorg; fscanf(datdeskr, "%ld%ld", &gruppe, &vorg); } if (gruppe != 0) fehler(14); /* Baum vervollstaendigen */ for (i=1;i<=maxgruppen;i++) { if (vater[i] >0) { if (vater[vater[i]] == -1) { /* Gruppennummer noch nicht vergeben */ vater[vater[i]] = 0; /* ist ein oberster Knoten */ } } } /* Sicherstellung, dass alle elementaren Gruppen im Baum */ /* aber auch keine unnoetigen */ grumax = maxgruppen; aenderunggruppen = true; unbenutztegruppenfreigeben(); } Static long ausdateigruppen() { long i, j, anz, gruppe, element, vorg; /* Elemente sind komprimiert!!! */ for (i=1; i<=zelmax;i++) blink[i] = false; for (i=1; i<=zelmax;i++) { if ((blink[i] == false)&&(group[i] !=0)) { anz = 0; gruppe = group[i]; fprintf(datdeskr, "%ld ",gruppe); for (j=i; j<=zelmax; j++) { if (group[j]==gruppe) { blink[j] = true; anz++; fprintf(datdeskr, "%ld ",j); if (anz >10) { anz = 0; fprintf(datdeskr, "\n"); } }/*if*/ }/* for j*/ fprintf(datdeskr, " 0\n"); /* Abschluss einer Gruppe */ } }/*for i*/ fprintf(datdeskr, " 0 \n"); /* Abschluss elementare Gruppen */ /* Ausgabe der relevanten Teile des Baums */ for (i=1;i<=grumax;i++) { if (vater[i] > 0) { fprintf(datdeskr, "%ld %ld\n", i, vater[i]); } } fprintf(datdeskr, "0 0"); /* Abschluss Knoten-Vater-Paare */ } Static Void einvorspannepc(datdeskr) FILE *datdeskr; { /* wegen readstdin ist die erste Zeile immer schon gelesen */ sscanf(eingabezeile, "%*[^123456789]%lg", &version); geteingabezeile(datdeskr); sscanf(eingabezeile, "%lg", &texfaktor); geteingabezeile(datdeskr); sscanf(eingabezeile, "%lg", &texdashl); geteingabezeile(datdeskr); sscanf(eingabezeile, "%lg", &texdotg); geteingabezeile(datdeskr); sscanf(eingabezeile, "%lg", &texinterd); if (version < 4.0) { geteingabezeile(datdeskr); sscanf(eingabezeile, "%lg", &gridw0); } if (version >= 10.0) { geteingabezeile(datdeskr); sscanf(eingabezeile, "%lg%lg%lg%lg%lg%lg%lg%lg", &gridw0, &gridw, &gridx0, &gridy0, &gridwx1, &gridwy1, &gridwx2, &gridwy2); } if (version >= 11.0) { geteingabezeile(datdeskr); sscanf(eingabezeile, "%*lg%*lg%*lg%*lg%*lg%*lg%lg%lg%d%d", &breite,&hoehe,&mitvorspann,&querformat); } } Static long einlesenelement(datdeskr,elseladr) FILE *datdeskr; long *elseladr; { /* auszuwertender String in eingabezeile bereits gelesen !!!! */ long i,k,anz; freieselement(&i); *elseladr = i; typ[i]=0; anz=sscanf(eingabezeile, "%ld%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%ld%ld%ld%lg%lg%lg", &typ[i], &x1[i], &y1_[i], &x2[i], &y2[i], &xb1[i], &yb1[i], &xb2[i], &yb2[i], &wanf[i], &wend[i], &linedicke[i], &lineende[i], &linetype[i], &laenge1[i], &laenge2[i], &rotwi[i]); if (typ[i] <= 0) return anz; if (rotwi[i] != 0.0) { crw[i] = cos(rotwi[i] * fgradbo); srw[i] = sin(rotwi[i] * fgradbo); } switch (typ[i]) { case tgerade: laenge1[i] = ppabstand(x1[i], y1_[i], x2[i], y2[i]); laenge2[i] = laenge1[i]; break; case trechteckgef: /*setzewinkel(i, x1[i], y1_[i], xb1[i], yb1[i]);*/ break; case tellbogen: case tellsektorgef: ellanfendpunkt(i); break; case tkreisbogen: case tkreissektorgef: kreisanfendpunkt(i); break; case ttext: freiestextel(&k); textno[i] = k; geteingabezeile(datdeskr); strcpy(texte[k],eingabezeile); textparam(i); break; }/*case*/ berechneminmax(i); return anz; } Static long eindatei(msel,dateiname,taste,phase) Char *dateiname; long *msel, taste, phase; { long i, k, anz; double xxmin,xxmax,yymin,yymax; Static Void init_neuezeichnung(); switch (phase) { case 0: goto L0; case 1: goto L1; case 2: goto L1B; default: goto L1; } L0: inittastaturtext(dateiname, pr2menue[*msel],0L); return 1; L1: strcpy(dateiname,EinText); if(istnullstr(dateiname)==true) goto L3; /*ohne Initialisieren*/ L1B: /* Einsprung nur fuer automatische Ausgabe */ datdeskr = fopen(dateiname, "r"); protokoll("open input file: ",dateiname); init_neuezeichnung(); /* mit Initialisieren */ if (datdeskr == NULL) { protokoll("can't open file ",dateiname); goto L3; } /* wegen readstdin muss die erste Zeile immer schon gelesen sein*/ geteingabezeile(datdeskr); einvorspannepc(datdeskr); while (1) { anz = geteingabezeile(datdeskr); if (anz == 0) fehler(3L); anz = einlesenelement(datdeskr,&i); if (typ[i] <= 0) goto L2; } /*while*/ L2: /*Ende*/ if (version >= 13.0) {/* Gruppen sind da!*/ eindateigruppen(datdeskr); } if (version < 11.0) { minmax(&xxmin,&xxmax,&yymin,&yymax); breite=(xxmax-xxmin)*texfaktor; hoehe=(yymax-yymin)*texfaktor; } if (datdeskr != NULL) fclose(datdeskr); datdeskr = NULL; L3: selmenloeschen(msel); ausalles(); konkat(winname,window_name,": "); konkat(winname,winname,dateiname); XStoreName(display,win,winname); return 0; } Static double dashlength() { return (texdashl / texfaktor); } Static double dotgap(i) { if (i==0) return (texdotg / texfaktor); else return (texdotg*(1+0.15*getlinedicke(i)) / texfaktor); } Static double interdotgap() { double h; h = texinterd / texfaktor; return h; } Static Void texpfeilaus(i, ende, xa, ya, dx, dy) long i, ende; double xa, ya, dx, dy; { long dxv, dyv; double w; if (lineende[i] == 0) return; if (lineende[i] == 4) return; if (ende == 1 && (lineende[i] == 1 || lineende[i] == 3)) { /*am Anfang*/ w = 2.0 * pi - winkel0(-dx, -dy, 1.0, 1.0) * fgradbo; fprintf(datdeskr, "\\aLdPfeil{%.3f,%.3f}{%.3f}{%d}\n", xa, ya, w, getlinedicke(i)); fputs(einrueck, datdeskr); } if (ende == 2 && (lineende[i] == 2 || lineende[i] == 3)) { /*am Ende*/ w = 2.0 * pi - winkel0(-dx, -dy, 1.0, 1.0) * fgradbo; fprintf(datdeskr, "\\eLdPfeil{%.3f,%.3f}{%.3f}{%d}\n", xa, ya, w, getlinedicke(i)); fputs(einrueck, datdeskr); } } Static Void texpfeilep(i,xa,ya,xe,ye) long i; double xa,ya,xe,ye; /* reduzierte Punkte */ /*bei tex ging put voraus*/ { double x0, y0, x, y, dx, dy; x0=x1[i]; y0=y1_[i]; x=x0; y=y0; dx=xa-x; dy=ya-y; texpfeilaus(i, 1L, x-x0, y-y0, dx, dy); x=x2[i]; y=y2[i]; dx=xe-x; dy=ye-y; texpfeilaus(i, 2L, x-x0, y-y0, dx, dy); } Static Void texpfeilew(i,redwa,redwe) long i; double redwa,redwe; /* Winkel im Bogenmass fuer reduzierten Bogen */ /*bei tex ging put und bei Ell. ggf rotiert voraus*/ { double lx, ly, w, x, y, dx, dy; lx = laenge1[i]; ly = laenge2[i]; w = wanf[i] * fgradbo; x = lx * cos(w); y = ly * sin(w); dx = lx * cos(redwa) - x; dy = ly * sin(redwa) - y; texpfeilaus(i, 1L, x, y, dx, dy); w = wend[i] * fgradbo; x = lx * cos(w); y = ly * sin(w); dx = lx * cos(redwe) - x; dy = ly * sin(redwe) - y; texpfeilaus(i, 2L, x, y, dx, dy); } Static double kuerzungsstrecke(elsel) long elsel; { /* Kuerzungsstrecke fuer Pfeile am Ende */ /* beim Aufrufer umzusetzen in Winkel bzw. Kuerzungsfaktoren */ double z; /*z ist zu kuerzende Strecke in pixels, abhaengig von Formel fuer */ /*stdpfeile in pst-latexdraw.sty */ /* Der Faktor 1.5 ergibt sich durch Vergroesserung des Faktors 1.33, */ /* welcher die x-Koordinate angibt, die beim Pfeil die Breite */ /* ergibt, die der Linienstaerke der Linie entspricht. Pfeil u.a. */ /* definiert in pst-latexdraw.sty durch */ /* (-8,-3) */ /* (1.33,0.5) */ /* (-8,0) (1.33,0) (0,0) */ /*jeweils skaliert mit Faktor f=linienstaerke in pts * 0.27 + 0.4 */ /* gemaess Makro .... \code{#1 .27 mul .4 add dup scale .... */ z=(getlinedicke(elsel)*lw2pt*0.27+0.4)*2.0/texfaktor; return z; } Static void pfeilreduktiongerade(elsel,xa,ya,xe,ye) long elsel; double *xa,*ya,*xe,*ye; { /* Verkuerzung der Geraden wegen Pfeilen am Ende */ double d,z,k,dx,dy; z = kuerzungsstrecke(elsel); d=ppabstand(*xa,*ya,*xe,*ye);/*Laenge der Geraden*/ if (d<=0.0) d=1.0; k=z/d; if (k > 0.5) k = 0.5; dx = k * (*xe); dy = k * (*ye); switch (lineende[elsel]) { case 1: *xa = dx; *ya = dy; break; case 2: *xe -= dx; *ye -= dy; break; case 3: *xa = dx; *ya = dy; *xe -= dx; *ye -= dy; break; }/*case*/ } Static double kuerzungswinkel(z,a,b,wa,wgr) double z,a,b,wa,wgr; /* Bestimmung von dw, um den Bogen bei wa zu kuerzen ist */ /* alle Winkel im Bogenmass, mathematisch */ /* wa und wgr begrenzen das sinnvolle Intervall und geben Richtung! */ { double xa,ya,dxa,dya,x,y,acw,asw,r,w,dw; xa = a*cos(wa); ya = b*sin(wa); dxa = a*sin(wa); dya = b*cos(wa); r = sqrt(dxa*dxa+dya*dya)+1.0; dw=z/r*fsign(wgr-wa)*0.05; w=wa; LL: x = a*cos(w); y = b*sin(w); if (ppabstand(x,y,xa,ya) >= z) { dw = w-wa-dw; return dw; } w += dw; if ( ((dw>0)&&(w<=wgr))||((dw<0)&&(w>=wgr)) ) goto LL; dw = w-wa-dw; return dw; } Static void pfeilreduktionbogen(elsel,redwa,redwe) long elsel; double *redwa,*redwe; { /* Verkuerzung der Boegen wegen Pfeilen am Ende */ /* redwa, redwe sind im Bogenmass, mathematisch, redwe > redwa */ /* redwa, redwe vorbesetzt!!! */ double mitte, a, b, z, dwa,dwe; a = laenge1[elsel]; b = laenge2[elsel]; if (*redwe <= *redwa) *redwe += 2.0*pi; mitte = (*redwe + *redwa)*0.5; z = kuerzungsstrecke(elsel); dwa = kuerzungswinkel(z, a, b, *redwa, mitte); dwe = kuerzungswinkel(z, a, b, *redwe, mitte); switch (lineende[elsel]) { case 1: *redwa += dwa; break; case 2: *redwe += dwe; break; case 3: *redwa += dwa; *redwe += dwe; break; }/*case*/ } Static Void austexgerade(i) long i; { double xa, ya, xe, ye, oxe, oye; /*relativ zu x1,y1*/ xa = 0.0; ya = 0.0; xe = x2[i] - x1[i]; /*relative Koordinaten*/ ye = y2[i] - y1_[i]; oxe=xe; oye=ye; putc('{', datdeskr); if (lineende[i] == 0) { if (linetype[i]==1) fprintf(datdeskr, "\\ldline(%.3f,%.3f)(%.3f,%.3f)}\n", xa, ya, xe, ye); else fprintf(datdeskr, "\\ldline[%d](%.3f,%.3f)(%.3f,%.3f)}\n", linetype[i], xa, ya, xe, ye); } else if (lineende[i] == 4) { /* capprojecting */ if (linetype[i]==1) fprintf(datdeskr, "\\ldcpline(%.3f,%.3f)(%.3f,%.3f)}\n", xa, ya, xe, ye); else fprintf(datdeskr, "\\ldcpline[%d](%.3f,%.3f)(%.3f,%.3f)}\n", linetype[i], xa, ya, xe, ye); } else { pfeilreduktiongerade(i,&xa,&ya,&xe,&ye); texpfeilep(i,xa+x1[i],ya+y1_[i],xe+x1[i],ye+y1_[i]); /* oxe,oye = Originalkoordinaten Endpunkt nicht verkuerzt */ fprintf(datdeskr, "\\LdpLine{%d}{(%.3f,%.3f)}[%d](%.3f,%.3f)(%.3f,%.3f)}\n", lineende[i], oxe, oye, linetype[i], xa, ya, xe, ye); /* zweite }, damit put geschlossen wird */ } } Static double radwinkeltotex(radianw) double radianw; { return (2.0 * pi - radianw); } Static double gradwinkeltotex(w) double w; { return (2.0 * pi - w * fgradbo);} Static Void texwinkel(wa,we, texwa, texwe) double wa, we, *texwa, *texwe; { /* Umrechnung math. Darstellung der Winkel in Darstellung in latex */ /* alle Winkel im Bogenmass */ *texwa = radwinkeltotex(we); *texwe = radwinkeltotex(wa); if (*texwe <= *texwa) *texwe += 2.0 * pi; } Static Void austexgefrechteck(i) long i; { double dx, dy; /* put bzgl. x1,y1 ging voraus*/ dx = ppabstand(x1[i], y1_[i], xb1[i], yb1[i]); dy = ppabstand(x1[i], y1_[i], xb2[i], yb2[i]); fprintf(datdeskr, "{\\rule{%.3lf\\unitlength}{%.3lf\\unitlength}}\n", dx,dy); } Static Void austexgefdreieck(i) long i; { double x2rel,y2rel, xb1rel, yb1rel; /* put bzgl. x1,y1 ging voraus*/ x2rel = x2[i]-x1[i]; y2rel = y2[i]-y1_[i]; xb1rel = xb1[i]-x1[i]; yb1rel = yb1[i]-y1_[i]; fprintf(datdeskr, "{\\gefdreieck(%.3lf,%.3lf)(%.3lf,%.3lf)}\n", x2rel,y2rel,xb1rel,yb1rel); /* erster und dritter Punkt ist Nullpunkt (d.h. relativ zu put!)*/ } Static Void austexgefviereck(i) long i; { double x2rel,y2rel, xb1rel, yb1rel, xb2rel, yb2rel; /* put bzgl. x1,y1 ging voraus*/ x2rel = x2[i]-x1[i]; y2rel = y2[i]-y1_[i]; xb1rel = xb1[i]-x1[i]; yb1rel = yb1[i]-y1_[i]; xb2rel = xb2[i]-x1[i]; yb2rel = yb2[i]-y1_[i]; fprintf(datdeskr, "{\\gefviereck(%.3lf,%.3lf)(%.3lf,%.3lf)(%.3lf,%.3lf)}\n", xb1rel,yb1rel,x2rel,y2rel,xb2rel,yb2rel); /* erster und vierter Punkt ist Nullpunkt (d.h. relativ zu put!)*/ } Static Void austexkreis(i) long i; { double wa, we, redwa, redwe, texwa, texwe, lx, zlx, otexwa,otexwe; /* put bzgl. x1,y1 ging voraus*/ putc('{', datdeskr); lx = laenge1[i]; zlx=2.0 * lx; wa = wanf[i] * fgradbo; we = wend[i] * fgradbo; redwa = wa; redwe = we; texwinkel(wa, we, &texwa, &texwe); otexwa = texwa; /*Originalwerte vor Adaption an Pfeile*/ otexwe = texwe; switch (typ[i]) { case tkreis: if (linetype[i]== 1) fprintf(datdeskr, "\\circle{%.3f}}\n", zlx); else fprintf(datdeskr, "\\circle[%d]{%.3f}}\n", linetype[i], zlx); break; case tkreisgef: fprintf(datdeskr, "\\circle*{%.3f}}\n", zlx); break; case tkreisbogen: if (lineende[i]==0) { if (linetype[i]== 1) fprintf(datdeskr, "\\arc{%.3f}{%.3f}{%.3f}}\n", zlx, texwa, texwe); else fprintf(datdeskr, "\\arc[%d]{%.3f}{%.3f}{%.3f}}\n", linetype[i], zlx, texwa, texwe); } else { pfeilreduktionbogen(i, &redwa, &redwe); texpfeilew(i,redwa,redwe); texwinkel(redwa, redwe, &texwa, &texwe); /* otexwa,otexwe = Originalwerte der Endpunkte */ fprintf(datdeskr, "\\LdpArc{%d}{%.3f}{%.3f}[%d]{%.3f}{%.3f}{%.3f}}\n", lineende[i],otexwa,otexwe,linetype[i], zlx, texwa, texwe); } break; case tkreissektorgef: wa=0.1*wanf[i]; we=0.1*wend[i]; fprintf(datdeskr,"\\pieslice{%.3f}{%.3f}{%.2f}{%.2f}}\n", zlx,zlx,wa,we); break; } } Static Void austexell(i) long i; { double wa, we, redwa, redwe, texwa, texwe, lx, ly, zlx, zly, otexwa, otexwe; /* put bzgl. x1,y1 ging voraus*/ putc('{', datdeskr); lx = laenge1[i]; ly = laenge2[i]; zlx=2.0 * lx; zly=2.0 * ly; wa = wanf[i] * fgradbo; we = wend[i] * fgradbo; redwa = wa; redwe = we; texwinkel(wa, we, &texwa, &texwe); otexwa=texwa; otexwe=texwe; switch (typ[i]) { case tell: if (linetype[i]== 1) fprintf(datdeskr, "\\ellipse{%.3f}{%.3f}}\n", zlx, zly); else fprintf(datdeskr, "\\ellipse[%d]{%.3f}{%.3f}}\n", linetype[i], zlx, zly); break; case tellgef: fprintf(datdeskr, "\\ellipse*{%.3f}{%.3f}}\n", zlx, zly); break; case tellbogen: if (lineende[i]==0) { if (linetype[i]== 1) fprintf(datdeskr, "\\ellarc{%.3f}{%.3f}{%.3f}{%.3f}}\n", zlx, zly,texwa, texwe); else fprintf(datdeskr, "\\ellarc[%d]{%.3f}{%.3f}{%.3f}{%.3f}}\n", linetype[i], zlx, zly, texwa, texwe); } else { pfeilreduktionbogen(i, &redwa,&redwe); texpfeilew(i,redwa,redwe); texwinkel(redwa, redwe, &texwa, &texwe); /* otexwa,otexwe = Originalwerte der Endpunkte */ fprintf(datdeskr, "\\LdpEllarc{%d}{%.3f}{%.3f}[%d]{%.3f}{%.3f}{%.3f}{%.3f}}\n", lineende[i],otexwa,otexwe,linetype[i], zlx, zly, texwa, texwe); } break; case tellsektorgef: wa=0.1*wanf[i]; we=0.1*wend[i]; fprintf(datdeskr,"\\pieslice{%.3f}{%.3f}{%.2f}{%.2f}}\n", zlx,zly,wa,we); break; } } Static Void pfeilreduktionbezier(elsel,nx0,ny0,nx1,ny1,nx2,ny2,nx3,ny3) long elsel; double *nx0,*ny0,*nx1,*ny1,*nx2,*ny2,*nx3,*ny3; { double z,d1,d2,t1,t2,dxdt,dydt; z = kuerzungsstrecke(elsel); d1= ppabstand(x1[elsel],y1_[elsel],xb1[elsel],yb1[elsel]); d2= ppabstand(x2[elsel],y2[elsel],xb2[elsel],yb2[elsel]); t1= z/(3.0*d1); t2= 1.0-z/(3.0*d2); switch (lineende[elsel]) { case 1: t2=1.0; break; case 2: t1=0.0; break; case 3: break; }/*case*/ punkt_bezier(elsel,t1,nx0,ny0); ableitung_bezier(elsel,t1,&dxdt,&dydt); *nx1=dxdt/3.0 + *nx0; *ny1=dydt/3.0 + *ny0; punkt_bezier(elsel,t2,nx3,ny3); ableitung_bezier(elsel,t2,&dxdt,&dydt); *nx2=-dxdt/3.0 + *nx3; *ny2=-dydt/3.0 + *ny3; } Static Void austexbezier(i) long i; { double nx0,ny0,nx1,ny1,nx2,ny2,nx3,ny3; /* neue Werte der Stuetzpunkte wegen Pfeilen*/ putc('{', datdeskr); if (lineende[i]==0) { if (linetype[i]==1) fprintf(datdeskr, "\\bezier(%.3f,%.3f)(%.3f,%.3f)(%.3f,%.3f)}\n", xb1[i] - x1[i], yb1[i] - y1_[i], xb2[i] - x1[i], yb2[i] - y1_[i], x2[i] - x1[i], y2[i] - y1_[i]); else fprintf(datdeskr, "\\bezier[%d](%.3f,%.3f)(%.3f,%.3f)(%.3f,%.3f)}\n", linetype[i], xb1[i] - x1[i], yb1[i] - y1_[i], xb2[i] - x1[i], yb2[i] - y1_[i], x2[i] - x1[i], y2[i] - y1_[i]); } else { pfeilreduktionbezier(i,&nx0,&ny0,&nx1,&ny1,&nx2,&ny2,&nx3,&ny3); texpfeilep(i,nx0,ny0,nx3,ny3); /*zunaechst Originalstuetzpunkte, dann neue Stuetzpunkte wegen Pfeilen */ fprintf(datdeskr, "\\LdpBezier{%d}(%.3f,%.3f)(%.3f,%.3f)(%.3f,%.3f)[%d](%.3f,%.3f)(%.3f,%.3f)(%.3f,%.3f)(%.3f,%.3f)}\n", lineende[i], xb1[i] - x1[i], yb1[i] - y1_[i], xb2[i] - x1[i], yb2[i] - y1_[i], x2[i] - x1[i], y2[i] - y1_[i], linetype[i], nx0 - x1[i], ny0 - y1_[i], nx1 - x1[i], ny1 - y1_[i], nx2 - x1[i], ny2 - y1_[i], nx3 - x1[i], ny3 - y1_[i]); } } Static Void austexbeziergef(i) long i; { putc('{', datdeskr); fprintf(datdeskr, "\\beziergef(%.3f,%.3f)(%.3f,%.3f)(%.3f,%.3f)}\n", xb1[i] - x1[i], yb1[i] - y1_[i], xb2[i] - x1[i], yb2[i] - y1_[i], x2[i] - x1[i], y2[i] - y1_[i]); } Static Void austextext(i) long i; { long lage, fontart; fontart = linetype[i]; lage = (long)floor(laenge2[i] + 0.5); fprintf(datdeskr, "{\\makebox(0,0)%s{%s%s}}\n", textausrichtung[lage],textfontmakro[fontart],texte[textno[i]]); } Static Void austexelement(i, xmin, ymin) long i; double xmin, ymin; { double rrot, xa, ya; long zcolor; zcolor=getzcolor(i,paint); rrot = 2.0 * pi - rotwi[i] * fgradbo; xa = x1[i] - xmin; ya = y1_[i] - ymin; if (rotwi[i] == 0.0) { if (zcolor==schwarz) fprintf(datdeskr, "\\put(%.3f,%.3f)",xa,ya); else fprintf(datdeskr, "\\putc(%.3f,%.3f){%d}", xa, ya, zcolor); } else { if (zcolor==schwarz) fprintf(datdeskr, "\\rput[%.3f](%.3f,%.3f)", rrot,xa,ya); else fprintf(datdeskr, "\\rputc[%.3f](%.3f,%.3f){%d}", rrot,xa,ya,zcolor); } switch (typ[i]) { /*case*/ case ttext: austextext(i); break; case tgerade: austexgerade(i); break; case trechteckgef: austexgefviereck(i); break; case tdreieckgef: austexgefdreieck(i); break; case tviereckgef: austexgefviereck(i); break; case tkreis: case tkreisgef: case tkreisbogen: case tkreissektorgef: austexkreis(i); break; case tell: case tellgef: case tellbogen: case tellsektorgef: austexell(i); break; case tbezier: austexbezier(i); break; case tbeziergef: austexbeziergef(i); break; } } Static Void auslinedicke(istdicke,solldicke) long *istdicke,solldicke; { double ptdicke; if (*istdicke != solldicke) { *istdicke=solldicke; ptdicke=lw2pt*solldicke; fprintf(datdeskr,"\\ldlinewidth{%d}{%.1lf}\n",solldicke,ptdicke); } } Static long austexdatei(msel, dateiname, taste, phase) Char *dateiname; long *msel,taste, phase; { long i, akttexldicke; double deltax, deltay, xxmax, yymax, xxmin, yymin; double fx, fy; Char altbh[maxstrl+1]; LANF: switch (phase) { case 0: goto L0; case 1: goto L1; case 2: goto L2; case 3: goto L3; case 4: goto L4; case 5: goto L5; case 6: goto L6; case 7: goto L7; } L0: strcpy(texdateiname,dateiname); trenneextension(texdateiname); konkat(texdateiname,texdateiname,".tex"); inittastaturtext(texdateiname,pr3menue[*msel],0L); return 1; L1: strcpy(texdateiname,EinText); if (istnullstr(texdateiname)==true) return 0; inittastaturtext(nullstr, "change output options ? (y/...)",0L); return 2; L2: if (*EinText!='y') goto L7; inittastaturtext(nullstr, "LaTeX file ready to copy into LaTeX source ? (y/...)",0L); return 3; L3: nmitvorspann=true; if (*EinText=='y') nmitvorspann=false; inittastaturtext(nullstr, "use old unitlength ? (y/...)",0L); return 4; L4: oldunitlength=false; if (*EinText=='y') { nbreite=breite; nhoehe=hoehe; oldunitlength=true; goto L5B; } L4B: sprintf(altbh,"%.1f %.1f",breite,hoehe); inittastaturtext(altbh, "maximum width and height of LaTeX picture in mm? (DIN A4:210 296): ",0L); return 5; L5: i=sscanf(EinText,"%lg%lg",&nbreite,&nhoehe); if ((i!=2)||(nbreite<10.0)||(nhoehe<10.0)) goto L4B; L5B: inittastaturtext(nullstr,"rotate LaTeX picture? (y/...)",0L); return 6; L6: /*Aenderungen erst durchfuehren, wenn Ausgabe wirklich erfolgt*/ querformat=true; if (*EinText=='y') querformat=false; mitvorspann=nmitvorspann; hoehe=nhoehe; breite=nbreite; if (oldunitlength==false) { minmax(&xxmin, &xxmax, &yymin, &yymax); deltax = xxmax - xxmin; if (deltax == 0.0) deltax = 1.0; deltay = yymax - yymin; if (deltay == 0.0) deltay = 1.0; fx = breite / deltax; fy = hoehe / deltay; if (fx <= fy) texfaktor = fx; else texfaktor = fy; } L7: minmax(&xxmin, &xxmax, &yymin, &yymax); deltax = xxmax - xxmin; if (deltax == 0.0) deltax = 1.0; deltay = yymax - yymin; if (deltay == 0.0) deltay = 1.0; datdeskr = fopen(texdateiname, "w"); protokoll(extfiletext,texdateiname); if (datdeskr == NULL) { protokoll("can't open file ",texdateiname); return 0; } if (mitvorspann==true) { fprintf(datdeskr, "%s\n",docstyle); fprintf(datdeskr, "\\begin{document}\n"); } fprintf(datdeskr, "\\setlength{\\unitlength}{%.3lfmm}\n",texfaktor); if (querformat==false) { fprintf(datdeskr, "\\begin{picture}(%.3f,%.3f)\n", deltay,deltax); fprintf(datdeskr, "\\rput[4.7124](%.3f,0){\n", deltay); } fprintf(datdeskr, "\\begin{picture}(%.3f,%.3f)\n", deltax,deltay); akttexldicke = -1; for (i = 1; i <= zelmax; i++) { if (typ[i] > 0) { auslinedicke(&akttexldicke,getlinedicke(i)); austexelement(i, xxmin, yymin); } } fprintf(datdeskr, "\\end{picture}\n"); if (querformat==false) fprintf(datdeskr, "}\\end{picture}\n"); if (mitvorspann==true) { fprintf(datdeskr, "\\end{document}\n"); } fprintf(datdeskr, "%s\n", blank); if (datdeskr != NULL) fclose(datdeskr); datdeskr = NULL; return 0; } Static Void ausskalieren() { double xmin, ymin, xmax, ymax, dx, dy, fx, fy, f; minmax(&xmin, &xmax, &ymin, &ymax); dx = xmax - xmin; dy = ymax - ymin; fx = 1.0; fy = 1.0; if (dx != 0.0) { if (dx < 0.5 * xzmax) fx = 0.5 * xzmax / dx; if (dx > 4.0 * xzmax) fx = 4.0 * xzmax / dx; } if (dy != 0.0) { if (dy < 0.5 * yzmax) fy = 0.5 * yzmax / dy; if (dy > 4.0 * yzmax) fy = 4.0 * yzmax / dy; } if (fx > fy) f = fy; else f = fx; pskalieren(&xmin, &ymin, 0.0, 0.0, f); pskalieren(&xmax, &ymax, 0.0, 0.0, f); dx = xmittelzei - (xmax + xmin) * 0.5; dy = ymittelzei - (ymax + ymin) * 0.5; elskalieren(&gridw, dx, dy, f); } Static long schreibenausdatei(msel,dateiname,taste,phase) Char *dateiname; long *msel,taste,phase; { long i; double xxmin, xxmax, yymin, yymax, dxpixel, dypixel; if (istnullstr(dateiname) == true) return 0; datdeskr = fopen(dateiname, "w"); if (datdeskr == NULL) { protokoll("can't open file ",dateiname); return 0; } kompakt(); protokoll(intfiletext,dateiname); minmax(&xxmin, &xxmax, &yymin, &yymax); dxpixel=xxmax-xxmin; dypixel=yymax-yymin; fprintf(datdeskr, "%s\n", window_name); fprintf(datdeskr, "% .5E (TEXFAKTOR)\n", texfaktor); fprintf(datdeskr, "% .5E (TEXDASHLAENGE)\n", texdashl); fprintf(datdeskr, "% .5E (TEXDOTGAP)\n", texdotg); fprintf(datdeskr, "% .5E (TEXINTERDOTGAP)\n", texinterd); fprintf(datdeskr, "%.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f (GITTERWERTE)\n", gridw0, gridw, gridx0, gridy0, gridwx1, gridwy1, gridwx2, gridwy2); fprintf(datdeskr, "%.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %d %d (AUSGABEOPTIONEN)\n", xxmin, yymin, xxmax, yymax, dxpixel, dypixel, breite, hoehe, mitvorspann, querformat); for (i = 1; i <= zelmax; i++) { if (typ[i] > 0) { fprintf(datdeskr, "%ld %.3lf %.3lf %.3lf %.3lf %.3lf %.3lf %.3lf %.3lf %.3lf %.3lf %ld %ld %ld %.3lf %.3lf %.3lf\n", typ[i],x1[i],y1_[i],x2[i],y2[i],xb1[i],yb1[i],xb2[i], yb2[i], wanf[i],wend[i],linedicke[i],lineende[i],linetype[i], laenge1[i],laenge2[i],rotwi[i]); if (typ[i] == ttext) /*text*/ fprintf(datdeskr, "%s\n", texte[textno[i]]); } } fprintf(datdeskr,"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"); ausdateigruppen(); if (datdeskr != NULL) fclose(datdeskr); datdeskr = NULL; return 0; } Static long ausdatei(msel,dateiname,taste,phase) Char *dateiname; long *msel,taste,phase; { long i; switch(phase) { case 0: goto L0; default: goto L1; } L0: inittastaturtext(dateiname,pr2menue[*msel],0L); return 1; L1: strcpy(dateiname,EinText); return schreibenausdatei(msel,dateiname,taste,phase); } Static long extendline(elsel, xa, ya) long elsel; double xa, ya; { double deltax, deltay, d1, d2, f, dx, dy; dx = x2[elsel] - x1[elsel]; dy = y2[elsel] - y1_[elsel]; d1 = ppabstand(xa, ya, x1[elsel], y1_[elsel]); d2 = ppabstand(xa, ya, x2[elsel], y2[elsel]); deltax = 0.0; deltay = 0.0; f = dx * dx + dy * dy; f = verlline / sifsqrt(1.0, f); deltax = dx * f; deltay = dy * f; if (d2 < d1) { /*verl bei x2,y2*/ x2[elsel] += deltax; y2[elsel] += deltay; } else { /*verl bei x1,y1*/ x1[elsel] -= deltax; y1_[elsel] -= deltay; } } Static long extendbogen(elsel, xa, ya) long elsel; double xa, ya; { double wa, we, wi; wa = wanf[elsel]; we = wend[elsel]; if (we < wa) we += wg; switch (typ[elsel]) { case tkreisbogen: case tkreissektorgef: wi = winkelk(x1[elsel], y1_[elsel], xa, ya); break; case tellsektorgef: case tellbogen: wi = winkelell(x1[elsel], y1_[elsel], laenge1[elsel], laenge2[elsel], crw[elsel], srw[elsel], xa, ya); break; } if (!((wi >= wa) && (wi <= we))) wi += wg; if (si_fabs(wi-wa) < si_fabs(wi-we)) { /* wa ausdehnen */ wa -= 150.0; } else {/* we ausdehnen */ we += 150.0; } if ((we-wa) >= wg) {/* voller Kreis bzw. volle Ellipse */ wanf[elsel] = 0.0; wend[elsel] = wg; switch (typ[elsel]) { case tkreisbogen: typ[elsel] = tkreis; break; case tkreissektorgef: typ[elsel] =tkreisgef; break; case tellsektorgef: typ[elsel] =tellgef; break; case tellbogen: typ[elsel] =tell; break; } return; } /* Bogen bleibt */ while (wa > wg) wa -= wg; while (we > wg) we -= wg; while (wa < 0.0) wa += wg; while (we < 0.0) we += wg; wanf[elsel] = wa; wend[elsel] = we; switch (typ[elsel]) { case tkreisbogen: case tkreissektorgef: kreisanfendpunkt(elsel);wi = winkelk(x1[elsel], y1_[elsel], xa, ya); break; case tellsektorgef: case tellbogen: ellanfendpunkt(elsel); break; } } Static long extend(xa, ya, msel, phase) long *msel,phase; double xa, ya; { long elsel; double deltax, deltay, d1, d2, f, dx, dy; switch (phase){ case 0: goto L0; case 1: goto L1; } L0: return 1; L1: sucheelement((long)nurextendel, &elsel, xa, ya); if (elsel==0) return 1; ausel(elsel, erase); switch (typ[elsel]) { case tgerade: extendline(elsel, xa, ya); break; case tkreisbogen: case tkreissektorgef: case tellsektorgef: case tellbogen: extendbogen(elsel, xa, ya); break; } berechneminmax(elsel); auselemente(); return 1; } Static long einbox(x,y,taste,msel,phase) long *msel,taste,phase; double x,y; { static long elsel; double dx, dy; switch (phase){ case 0: goto L0; case 1: goto L1; case 2: goto L2; } L0: return 1; L1: freieselement(&elsel); x1[elsel]=x; y1_[elsel]=y; strcpy(pr4, pr3menue[*msel]); return 2; L2: x2[elsel]=x; y2[elsel]=y; dx = x2[elsel] - x1[elsel]; dy = y2[elsel] - y1_[elsel]; if (si_fabs(dx) < 2.0 || si_fabs(dy) < 2.0) return 2; if (dx < 0) { dx = -dx; ftausch(&x1[elsel], &x2[elsel]); } if (dy < 0) { dy = -dy; ftausch(&y1_[elsel], &y2[elsel]); } xb1[elsel] = x1[elsel] + dx; yb1[elsel] = y1_[elsel]; xb2[elsel] = x1[elsel]; yb2[elsel] = y1_[elsel] + dy; if (selmenue[mgefuellt]==true) { /*gefuelltes Rechteck*/ typ[elsel] = trechteckgef; setlineattribute(0L, elsel); berechneminmax(elsel); ausel(elsel, paint); return 0; } createline(0L, x1[elsel], y1_[elsel], xb1[elsel], yb1[elsel]); createline(0L, xb1[elsel], yb1[elsel], x2[elsel], y2[elsel]); createline(0L, x2[elsel], y2[elsel], xb2[elsel], yb2[elsel]); createline(0L, xb2[elsel], yb2[elsel], x1[elsel], y1_[elsel]); typ[elsel] = 0; return 0; } Static long einboxll(xa,ya,msel,phase) long *msel,phase; double xa, ya; /* Ergaenzung zum Parallelogramm */ { static long elsel1, elsel2; switch (phase){ case 0: goto L0; case 1: goto L1; case 2: goto L2; } L0: strcpy(pr4, pr2menue[*msel]); return 1; L1: sucheelement((long)nurgerade, &elsel1, xa, ya); if (elsel1==0) return 1; strcpy(pr4, pr3menue[*msel]); return 2; L2: sucheelement((long)nurgerade, &elsel2, xa, ya); if (elsel2==0) return 2; ergbox(elsel1, elsel2); return 0; } Static long eindreieck(x,y,taste,msel,phase) long *msel,taste,phase; double x,y; { static long elsel; switch (phase){ case 0: goto L0; case 1: goto L1; case 2: goto L2; case 3: goto L3; } L0: return 1; L1: freieselement(&elsel); x1[elsel]=x; y1_[elsel]=y; strcpy(pr4, pr3menue[*msel]); return 2; L2: x2[elsel]=x; y2[elsel]=y; if (ppabstand(x2[elsel], y2[elsel],x1[elsel],y1_[elsel]) < 3.0) return 2; strcpy(pr4,prpoint3); return 3; L3: xb1[elsel]=x; yb1[elsel]=y; if (ppabstand(xb1[elsel], yb1[elsel],x1[elsel],y1_[elsel]) < 3.0) return 3; if (ppabstand(xb1[elsel], yb1[elsel],x2[elsel],y2[elsel]) < 3.0) return 3; if (selmenue[mgefuellt]==true) { /*gefuelltes Dreieck*/ typ[elsel] = tdreieckgef; setlineattribute(0L, elsel); berechneminmax(elsel); ausel(elsel, paint); return 0; } createline(0L, x1[elsel], y1_[elsel], xb1[elsel], yb1[elsel]); createline(0L, xb1[elsel], yb1[elsel], x2[elsel], y2[elsel]); createline(0L, x2[elsel], y2[elsel], x1[elsel], y1_[elsel]); typ[elsel] = 0; return 0; } Static long einviereck(x,y,taste,msel,phase) long *msel,taste,phase; double x,y; { static long elsel; switch (phase){ case 0: goto L0; case 1: goto L1; case 2: goto L2; case 3: goto L3; case 4: goto L4; } L0: return 1; L1: freieselement(&elsel); x1[elsel]=x; y1_[elsel]=y; strcpy(pr4, pr3menue[*msel]); return 2; L2: xb1[elsel]=x; yb1[elsel]=y; if (ppabstand(xb1[elsel], yb1[elsel],x1[elsel],y1_[elsel]) < 3.0) return 2; strcpy(pr4,prpoint3); return 3; L3: x2[elsel]=x; y2[elsel]=y; if (ppabstand(x2[elsel], y2[elsel],xb1[elsel],yb1[elsel]) < 3.0) return 3; if (ppabstand(x2[elsel], y2[elsel],x1[elsel],y1_[elsel]) < 3.0) return 3; strcpy(pr4,prpoint4); return 4; L4: xb2[elsel]=x; yb2[elsel]=y; if (ppabstand(xb2[elsel], yb2[elsel],x1[elsel],y1_[elsel]) < 3.0) return 4; if (ppabstand(xb2[elsel], yb2[elsel],xb1[elsel],yb1[elsel]) < 3.0) return 4; if (ppabstand(xb2[elsel], yb2[elsel],x2[elsel],y2[elsel]) < 3.0) return 4; if (selmenue[mgefuellt]==true) { /*gefuelltes Viereck*/ typ[elsel] = tviereckgef; setlineattribute(0L, elsel); berechneminmax(elsel); ausel(elsel, paint); return 0; } createline(0L, x1[elsel], y1_[elsel], xb1[elsel], yb1[elsel]); createline(0L, xb1[elsel], yb1[elsel], x2[elsel], y2[elsel]); createline(0L, x2[elsel], y2[elsel], xb2[elsel], yb2[elsel]); createline(0L, xb2[elsel], yb2[elsel], x1[elsel], y1_[elsel]); typ[elsel] = 0; return 0; } Static Void setlagetext(elsel) long elsel; { /* Lage Text relativ zum Anklickpunkt bestimmen und alle davon */ /* abhaengigen Parameter im Zeichnungselement setzen */ long lrtb; lrtb = 1; if (selmenue[mbtext]==true) lrtb = 3; if (selmenue[mttext]==true) lrtb = 6; if (selmenue[mltext]==true) { lrtb = 7; if (selmenue[mbtext]==true) lrtb = 0; if (selmenue[mttext]==true) lrtb = 4; } if (selmenue[mrtext]==true) { lrtb = 8; if (selmenue[mbtext]==true) lrtb = 2; if (selmenue[mttext]==true) lrtb = 5; } laenge2[elsel] = lrtb; textparam(elsel); berechneminmax(elsel); } Static long eintext(x,y,xa,ya,taste,msel,phase) long *msel,taste,phase; double x,y,xa,ya; { static long elsel, tsel; long elselg; double dx,dy; switch (phase) { case 0: goto L0; case 1: goto L1; case 2: goto L2; case 3: goto L3; case 4: goto L4; case 5: goto L5; default: goto L6; /*fuer Textzeichen */ } L0: texterase=0L; return 1; L1: for (elsel = 1; elsel <= zelmax; elsel++) { if (typ[elsel] != ttext) continue; if (si_fabs(y1_[elsel] - y) > 0.5) continue; if (si_fabs(x1[elsel] - x) > 0.5) continue; tsel = textno[elsel]; ausel(elsel, erase); texterase=elsel; zeichnen = true; setzeakttextfont(elsel); goto L5; /*Text zu modifizieren*/ } texterase=0L; freieselement(&elsel); freiestextel(&tsel); x1[elsel] = x; y1_[elsel] = y; if (selmenue[mparallel]==false) goto L4; strcpy(pr4, pr2menue[mparallel]); return 2; L2: x2[elsel] = xa; y2[elsel] = ya; strcpy(pr4, pr3menue[mparallel]); return 3; L3: sucheelement((long)nurgerade, &elselg, xa, ya); if (elselg==0) return 3; strcpy(pr4,pr2menue[*msel]); dx = si_fabs(x2[elselg] - x1[elselg]); if ((x2[elsel] - x1[elsel]) < 0.0) dx = -dx; dy = si_fabs(y2[elselg] - y1_[elselg]); if ((y2[elsel] - y1_[elsel]) < 0.0) dy = - dy; x2[elsel] = x1[elsel] + dx; y2[elsel] = y1_[elsel] + dy; setzewinkel(elsel, x1[elsel], y1_[elsel], x2[elsel], y2[elsel]); L4: setlineattribute(0L,elsel); linetype[elsel] = stdfontnummer; textno[elsel] = tsel; strcpy(texte[tsel],nullstr); L5: inittastaturtext(texte[tsel], "text: ",0L); return 6; L6: strcpy(texte[tsel], EinText); if (istnullstr(texte[tsel]) == true) { typ[elsel] = 0; texterase=0L; return 0; } typ[elsel] = ttext; if (fontnummer != stdfontnummer) linetype[elsel] = fontnummer; setlagetext(elsel); texterase=0L; ausel(elsel, paint); return 0; } Static Void initelemente() { long i; for (i = 0; i <= zel; i++) { typ[i] = 0; /*Element frei*/ textno[i] = 0; } for (i = 1; i <= zstr; i++) strcpy(texte[i],nullstr); zelmax = 0; } Static Void drehpunkt(x1r, y1r, dx, dy, cd, sd, v, xp, yp) double x1r, y1r, dx, dy, cd, sd, v, *xp, *yp; { double xx, yy; /*Drehpunkt x1r,y1r*/ /*positiver Drehwinkel def. durch cd,sd*/ /*Vergroesserung v*/ /*Translation um dx,dy*/ translation(x1r, y1r, *xp, *yp, &xx, &yy); xx *= v; yy *= v; rotation(cd, -sd, &xx, &yy); translation(-dx, -dy, xx, yy, xp, yp); } Static Void drehpunkt1(i, x1r, y1r, dx, dy, cd, sd, v) long i; double x1r, y1r, dx, dy, cd, sd, v; { drehpunkt(x1r, y1r, dx, dy, cd, sd, v, &x1[i], &y1_[i]); } Static Void drehpunkt2(i, x1r, y1r, dx, dy, cd, sd, v) long i; double x1r, y1r, dx, dy, cd, sd, v; { drehpunkt(x1r, y1r, dx, dy, cd, sd, v, &x2[i], &y2[i]); } Static Void drehpunktb(i, x1r, y1r, dx, dy, cd, sd, v) long i; double x1r, y1r, dx, dy, cd, sd, v; { drehpunkt(x1r, y1r, dx, dy, cd, sd, v, &xb1[i], &yb1[i]); drehpunkt(x1r, y1r, dx, dy, cd, sd, v, &xb2[i], &yb2[i]); } Static Void drehell0(i, xr1, yr1, dx, dy, cd, sd, v) long i; double xr1, yr1, dx, dy, cd, sd, v; { double xl, yl, lx, ly; lx = laenge1[i]; ly = laenge2[i]; ell_xy(x1[i], y1_[i], lx, ly, crw[i], srw[i], lx, 0.0, &xl, &yl); drehpunkt(xr1, yr1, dx, dy, cd, sd, v, &xl, &yl); drehpunkt1(i, xr1, yr1, dx, dy, cd, sd, v); laenge1[i] = lx * v; laenge2[i] = ly * v; setzewinkel(i, x1[i], y1_[i], xl, yl); } Static Void drehell(i, xr1, yr1, dx, dy, cd, sd, v) long i; double xr1, yr1, dx, dy, cd, sd, v; { drehell0(i, xr1, yr1, dx, dy, cd, sd, v); } Static Void drehellbogen(i, xr1, yr1, dx, dy, cd, sd, v) long i; double xr1, yr1, dx, dy, cd, sd, v; { double xm, ym, lx, ly, cr, sr; drehpunktb(i, xr1, yr1, dx, dy, cd, sd, v); drehell0(i, xr1, yr1, dx, dy, cd, sd, v); ellpar(i, &xm, &ym, &lx, &ly, &cr, &sr); wanf[i] = winkelell(xm, ym, lx, ly, cr, sr, xb1[i], yb1[i]); wend[i] = winkelell(xm, ym, lx, ly, cr, sr, xb2[i], yb2[i]); ellanfendpunkt(i); } Static Void drehkbogen(i, xr1, yr1, dx, dy, cd, sd, v) long i; double xr1, yr1, dx, dy, cd, sd, v; { drehpunkt1(i, xr1, yr1, dx, dy, cd, sd, v); drehpunktb(i, xr1, yr1, dx, dy, cd, sd, v); laenge1[i] *= v; laenge2[i] *= v; wanf[i] = winkelk(x1[i], y1_[i], xb1[i], yb1[i]); wend[i] = winkelk(x1[i], y1_[i], xb2[i], yb2[i]); } Static boolean testnotin(x, y, xa, ya, xe, ye) double x, y, xa, ya, xe, ye; { boolean Result; Result = true; if (xa > xe) ftausch(&xa,&xe); if (x < xa) goto _L1; if (x > xe) goto _L1; if (ya > ye) ftausch(&ya,&ye); if (y < ya) goto _L1; if (y > ye) goto _L1; Result = false; _L1: return Result; } Static boolean schnittellgeradeda(elsel,xa,ya,xe,ye) long elsel; double xa,ya,xe,ye; { long i, anz; double w; terg wgerade, well; Static Void gell00schnittp(); gell00schnittp(xa,ya,xe,ye,elsel,&anz,wgerade,well,false); if (anz==0) return false; for (i = 1; i <= anz; i++) { if ((wgerade[i]>=0.0)&&(wgerade[i] <= 1.0)) return true; } return false; } Static boolean elementinre(xa, ya, xe, ye, i) double xa, ya, xe, ye; long i; { boolean Result; if (typ[i] <= 0) return false; if (xa > xe) ftausch(&xa,&xe); if (ya > ye) ftausch(&ya,&ye); if ((elxmin[i] >= xa)&&(elxmax[i] <= xe)&& (elymin[i] >= ya)&&(elymax[i] <= ye)) return true; return false; } Static boolean blinkgruppeninre(xa,ya,xe,ye,elselmin) double xa,ya,xe,ye; long elselmin; { /* Gruppen im Rechteck, aber erst ab elselmin beachtet */ /* Nur neu selektierte Elemente: blink == true */ /* Nur neu selektierte Gruppen : gruppentag == true */ long i,j,g, etwasgetan, anz; /* blinkenan(); schon gegeben in blinkelemente !! */ /* blinkend = false; schon gegeben in blinkelemente !! */ initgruppentag(unbekannt); anz = 0; for (i=elselmin;i<=zelmax;i++) { if (typ[i]>0) { g = group[i]; if (g==0) { if (elementinre(xa, ya, xe, ye, i)==true) { anz++; blink[i] = true; } continue; } if (gruppentag[g] == false) continue; /* gruppentag unbekannt oder true */ if (elementinre(xa, ya, xe, ye, i)==true) { gruppentag[g] = true; } else markteilbaum(g,false); } } /* jetzt Gruppenbaum untersuchen */ etwasgetan = true; while (etwasgetan == true) { etwasgetan = false; for (i=1;i<=grumax;i++) { if ( (gruppentag[i] == unbekannt)|| (gruppentag[i] == true) ) { j = 1; while ( (g=sohn(j,i)) != 0) {/* j. Sohn von i untersuchen */ j++; if (gruppentag[g] == true) continue; if (gruppentag[g] == unbekannt) break; if (gruppentag[g] == false) { markteilbaum(i, false); etwasgetan = true; break; } } if (g==0) { /* Schleife normal zu Ende, alle Soehne true */ if (gruppentag[i] != true) { gruppentag[i] = true; etwasgetan = true; } } }/* end if unbekannt */ }/*end Durchlauf durch Gruppen */ }/*solange etwas getan */ /* Alle Gruppen muessten jetzt bekannt sein, kein Test dafuer! */ /* Elemente nur in Rechteck, wenn Gruppe in Rechteck */ for (i=elselmin;i<=zelmax;i++) { if (typ[i]>0) { g = group[i]; if ((g != 0) && (gruppentag[g] == true)) { anz++; blink[i] = true; } } } if (anz > 0) return true; blinkenaus(); return false; } Static boolean zukleineselement(i) long i; {/*Pruefung, ob Element i zu klein beim kopieren */ double minabm; minabm = 0.1; if (typ[i] <= 0) return true; switch (typ[i]) { case ttext: /*Text*/ return false; case tgerade: /*Gerade*/ if (ppabstand(x1[i], y1_[i], x2[i], y2[i]) < minabm) goto zuklein; break; case trechteckgef: case tviereckgef: if (ppabstand(x1[i], y1_[i], x2[i], y2[i]) < minabm) goto zuklein; break; case tdreieckgef: if (ppabstand(x1[i], y1_[i], x2[i], y2[i]) < minabm) goto zuklein; break; case tkreis: case tkreisgef: /*Kreis*/ if (laenge1[i] < minabm) goto zuklein; break; case tkreisbogen: /*Kreisbogen*/ case tkreissektorgef: if (laenge1[i] < minabm) goto zuklein; break; case tell: case tellgef: /*Ellipse*/ if ((laenge1[i] < minabm) ||(laenge2[i] < minabm)) goto zuklein; break; case tellbogen: /*Ellipsenbogen*/ case tellsektorgef: if ((laenge1[i] < minabm)|| (laenge2[i] < minabm)) goto zuklein; break; case tbezier: /*Bezier*/ case tbeziergef: if (ppabstand(x1[i], y1_[i], xb1[i], yb1[i]) < minabm) goto zuklein; if (ppabstand(x2[i], y2[i], xb2[i], yb2[i]) < minabm) goto zuklein; break; }/*case*/ return false; /* zu klein */ zuklein: typ[i] = 0; return true; } Static long duplikat0(i,vollst) long i; boolean vollst; {/* Nummer j eines Zeichnungselements ist Ergebnis */ /* falls j != 0 ist j ein vorhandenes Duplikat zu i */ /* falls vollst == false werden */ /* lineende[i], linedicke[i], linetype[i] nicht beruecksichtigt */ long j; for (j = 1; j <= zelmax; j++) { if (typ[j] <= 0) continue; if ((typ[i] != typ[j]) || (i == j)) continue; if (group[i] != group[j]) continue; if (nglx(x1[i], x1[j])== false) continue; if (nglx(y1_[i], y1_[j])== false) continue; if (nglw(rotwi[i], rotwi[j])==false) continue; if (vollst == true) { if (lineende[i] != lineende[j]) continue; if (linedicke[i] != linedicke[j]) continue; if (linetype[i] != linetype[j]) continue; } switch (typ[i]) { case ttext: /*Text*/ if (strvergl(texte[textno[i]], texte[textno[j]])==true) goto gleich; break; case tgerade: /*Gerade*/ if (nglx(x2[i], x2[j])==false) continue; if (nglx(y2[i], y2[j])==false) continue; goto gleich; case trechteckgef: case tviereckgef: if (nglx(x2[i], x2[j])==false) continue; if (nglx(y2[i], y2[j])==false) continue; if (nglx(xb1[i], xb1[j])==false) continue; if (nglx(yb1[i], yb1[j])==false) continue; if (nglx(xb2[i], xb2[j])==false) continue; if (nglx(yb2[i], yb2[j])==false) continue; goto gleich; case tdreieckgef: if (nglx(x2[i], x2[j])==false) continue; if (nglx(y2[i], y2[j])==false) continue; if (nglx(xb1[i], xb1[j])==false) continue; if (nglx(yb1[i], yb1[j])==false) continue; goto gleich; case tkreis: case tkreisgef: /*Kreis*/ if (nglx(laenge1[i], laenge1[j])==false) continue; goto gleich; case tkreisbogen: /*Kreisbogen*/ case tkreissektorgef: if (nglx(laenge1[i], laenge1[j])==false) continue; if (nglw(wanf[i], wanf[j])==false) continue; if (nglw(wend[i], wend[j])==false) continue; goto gleich; case tell: case tellgef: /*Ellipse*/ if (nglx(laenge1[i], laenge1[j])==false) continue; if (nglx(laenge2[i], laenge2[j])==false) continue; goto gleich; case tellbogen: /*Ellipsenbogen*/ case tellsektorgef: if (nglx(laenge1[i], laenge1[j])==false) continue; if (nglx(laenge2[i], laenge2[j])==false) continue; if (nglw(wanf[i], wanf[j])==false) continue; if (nglw(wend[i], wend[j])==false) continue; goto gleich; case tbezier: /*Bezier*/ case tbeziergef: if (nglx(x2[i], x2[j])==false) continue; if (nglx(y2[i], y2[j])==false) continue; if (nglx(xb1[i], xb1[j])==false) continue; if (nglx(yb1[i], yb1[j])==false) continue; if (nglx(xb2[i], xb2[j])==false) continue; if (nglx(yb2[i], yb2[j])==false) continue; goto gleich; }/*case*/ } /*for j*/ /*keine Duplikate*/ return 0; gleich: /* Duplikat */ return j; } Static boolean duplikat(i) long i; {/* zu kleine Abmessungen oder volles Duplikat */ long j; if (zukleineselement(i)==true) return true; if ( (j=duplikat0(i,true))==0) return false; loescheelement(i); return true; } Static Void kopeinel(elsel, xr1, yr1, dx, dy, v, cd, sd, kop, loeschen) long elsel; double xr1, yr1, dx, dy, v, cd, sd; boolean kop; long loeschen; { long i; if (kop==true) { /*kopieren*/ freieselement(&i); kopunv(elsel, i); } else { /*verschieben*/ i = elsel; if (loeschen==1) ausel(i, erase); zeichnen = true; } switch (typ[i]) { case ttext: /*Text*/ drehpunkt1(i, xr1, yr1, dx, dy, cd, sd, v); drehpunkt2(i, xr1, yr1, dx, dy, cd, sd, v); drehpunktb(i, xr1, yr1, dx, dy, cd, sd, v); setzewinkel(i, xb1[i], yb1[i], xb2[i], yb2[i]); textparam(i); break; case tgerade: drehpunkt1(i, xr1, yr1, dx, dy, cd, sd, v); drehpunkt2(i, xr1, yr1, dx, dy, cd, sd, v); break; case trechteckgef: drehpunkt1(i, xr1, yr1, dx, dy, cd, sd, v); drehpunkt2(i, xr1, yr1, dx, dy, cd, sd, v); drehpunktb(i, xr1, yr1, dx, dy, cd, sd, v); /*setzewinkel(i, x1[i], y1_[i], xb1[i], yb1[i]);*/ break; case tdreieckgef: case tviereckgef: drehpunkt1(i, xr1, yr1, dx, dy, cd, sd, v); drehpunkt2(i, xr1, yr1, dx, dy, cd, sd, v); drehpunktb(i, xr1, yr1, dx, dy, cd, sd, v); break; case tkreis: case tkreisgef: drehpunkt1(i, xr1, yr1, dx, dy, cd, sd, v); laenge1[i] *= v; laenge2[i] *= v; break; case tkreisbogen: case tkreissektorgef: drehkbogen(i, xr1, yr1, dx, dy, cd, sd, v); break; case tell: case tellgef: drehell(i, xr1, yr1, dx, dy, cd, sd, v); break; case tellbogen: case tellsektorgef: drehellbogen(i, xr1, yr1, dx, dy, cd, sd, v); break; case tbezier: case tbeziergef: drehpunkt1(i, xr1, yr1, dx, dy, cd, sd, v); drehpunkt2(i, xr1, yr1, dx, dy, cd, sd, v); drehpunktb(i, xr1, yr1, dx, dy, cd, sd, v); break; }/*case*/ if (kop==true) { /*kopieren*/ bestimmeneuegruppe(i); if (duplikat(i)==false) { berechneminmax(i); ausel(i, paint); } } else /*verschieben*/ berechneminmax(i); ausel(i, paint); } Static boolean testkop(elsel, relsel, zelsel, kop) long elsel, relsel, zelsel; boolean kop; { if (kop==true) /*Referenzstrecke und Zielstrecke mitkopieren*/ return (elsel != 0); else /*Referenzstrecke und Zielstrecke nicht verschieben*/ if (elsel != 0 && elsel != zelsel && elsel != relsel) return true; else return false; } Static Void kopel(xanf, yanf, xend, yend, xr1, yr1, dx, dy, v, cd, sd, msel, kop, relsel, zelsel) double xanf, yanf, xend, yend, xr1, yr1, dx, dy, v, cd, sd; long *msel; boolean kop; long relsel, zelsel; { long elsel,elselmin,zelmaxalt; elselmin = 1; while (blinkelemente(xanf, yanf, xend, yend,elselmin) == true) { if (kop == true) gruppenumbenennen(); zelmaxalt = zelmax; for (elsel=elselmin;elsel <= zelmaxalt; elsel++) { if (blink[elsel] == true) { if (testkop(elsel, relsel, zelsel, kop)==true) { kopeinel(elsel, xr1, yr1, dx, dy, v, cd, sd, kop, 1L); } } } unbenutztegruppenfreigeben(); if (xanf == xend) { /*Ein Element angeklickt*/ blinkenaus(); return; } /* Auswahlrechteck, evtl. neue Elemente darin */ elselmin = zelmaxalt+1; if (tastegedrueckt()!=0) return; } /*while */ } Static long abbundkopieren(x,y,xanf,yanf,xend,yend,taste,msel,phase,kop) long *msel,phase,taste; double x,y,xanf,yanf,xend,yend; boolean kop; { static long relsel, zelsel; double x1r, y1r, x1z, y1z, dx, dy, dr, dz, v, cr, sr, cz, sz, cd, sd; switch (phase){ case 0: goto L0; case 1: goto L1; case 2: goto L2; case 3: goto L3; } L0: /* kompakt(); */ strcpy(pr4, pr2menue[*msel]); return 1; L1: sucheelement((long)nurgerade, &relsel, xanf, yanf); if (relsel==0) return 1; dr = ppabstand(x1[relsel], y1_[relsel], x2[relsel], y2[relsel]); if (dr == 0.0) return 1; strcpy(pr4, pr3menue[*msel]); return 2; L2: sucheelement((long)nurgerade, &zelsel, xanf, yanf); if (zelsel==0) return 2; dz = ppabstand(x1[zelsel], y1_[zelsel], x2[zelsel], y2[zelsel]); if (dz == 0.0) return 2; strcpy(pr4," object(s)?"); return 3; L3: x1r = x1[relsel]; y1r = y1_[relsel]; x1z = x1[zelsel]; y1z = y1_[zelsel]; dx = x2[zelsel] - x1[zelsel]; dy = y2[zelsel] - y1_[zelsel]; dz = ppabstand(x1[zelsel], y1_[zelsel], x2[zelsel], y2[zelsel]); dr = ppabstand(x1[relsel], y1_[relsel], x2[relsel], y2[relsel]); v = dz / dr; cz = dx / dz; sz = dy / dz; dx = x2[relsel] - x1[relsel]; dy = y2[relsel] - y1_[relsel]; cr = dx / dr; sr = dy / dr; addtheorem(cz, sz, cr, -sr, &cd, &sd); /*wz-wr*/ kopel(xanf, yanf, xend, yend, x1r, y1r, x1z, y1z, v, cd, sd, msel, kop, relsel, zelsel); return 3; } Static long translundkopieren(x,y,xanf,yanf,xend,yend,taste,msel,phase,kop) long *msel,phase,taste; double x,y,xanf,yanf,xend,yend; boolean kop; { long i, elsel; static long relsel; switch (phase){ case 0: goto L0; case 1: goto L1; case 2: goto L2; case 3: goto L3; } L0: freieselement(&relsel); strcpy(pr4," object(s)?"); return 1; L1: if (blinkelemente(xanf,yanf,xend,yend,1L) == false) return 1; blinkend = true; if (xanf == xend) {/* ein Element war selektiert */ x1[relsel] = x; y1_[relsel] = y; strcpy(pr4, pr3menue[mkopbewmaus]); return 3; } /* Auswahlrechteck war gegeben */ strcpy(pr4, pr2menue[mkopbewmaus]); return 2; L2: /*Referenzpunkt angeben*/ x1[relsel] = x; y1_[relsel] = y; strcpy(pr4, pr3menue[mkopbewmaus]); return 3; L3: if (kop==true) gruppenumbenennen(); /*Zielpunkt angeben*/ for (elsel = 1; elsel <= zelmax; elsel++) { if (blink[elsel] == true) kopeinel(elsel, x1[relsel], y1_[relsel], x, y, 1.0, 1.0, 0.0, kop,1L); } if (kop==true) return 3; strcpy(pr4," object(s)?"); blinkenaus(); return 1; } Static long kopieren(x,y,xa,ya,xe,ye,taste,msel,phase) long *msel,phase,taste; double x,y,xa,xe,ya,ye; { if (selmenue[mkopbewmaus]==true) phase=translundkopieren(x,y,xa,ya,xe,ye,taste,msel,phase,true); else phase=abbundkopieren(x,y,xa,ya,xe,ye,taste,msel,phase,true); return phase; } Static long bewegen(x,y,xa,ya,xe,ye,taste,msel,phase) long *msel,phase,taste; double x,y,xa,xe,ya,ye; { if (selmenue[mkopbewmaus]==true) phase=translundkopieren(x,y,xa,ya,xe,ye,taste,msel,phase,false); else phase=abbundkopieren(x,y,xa,ya,xe,ye,taste,msel,phase,false); return phase; } Static long rotieren(x,y,xanf,yanf,xend,yend,taste,msel,phase) long *msel,phase,taste; double x,y,xanf,yanf,xend,yend; /* Rotation ein Objekt, eine Gruppe um den Anklickpunkt*/ { double xr,yr,xz,yz,v,cd,sd,wi; long elsel, elselmin; boolean kop; static boolean auswrechteck; switch (phase){ case 0: goto L0; case 1: goto L1; case 2: goto L2; } L0: auswrechteck = false; return 1; L1: if (blinkelemente(xanf,yanf,xend,yend,1L) == false) return 1; blinkend = true; if (xanf == xend) /* ein Element war selektiert */ goto L2; /* Auswahlrechteck war gegeben, Drehpunkt abfragen */ auswrechteck = true; strcpy(pr4, pr3menue[mrot]); return 2; L2: /*Drehpunkt jetzt bekannt*/ v = 1.0; xr = x; yr = y; xz = xr; yz = yr; wi= winkelrotate; wi = wi*pi/180.0; cd = cos(wi); sd = sin(wi); kop = false; for (elsel=1;elsel <= zelmax; elsel++) { if (blink[elsel] == true) { kopeinel(elsel, xr, yr, xz, yz, v, cd, sd, kop, 1L); } } if (auswrechteck == false) { /* kein Auswahlrechteck, neue Objekte selektieren */ strcpy(pr4,pr2menue[mrot]); blinkenaus(); return 1; } /* Auswahlrechteck vorhanden, neue Drehung?? */ return 2; } Static long vorber_export(x,y,xa,ya,xe,ye,taste,msel,phase) long *msel,phase,taste; double x,y,xa,xe,ya,ye; { long i, elsel; static long kmark, relsel; switch (phase){ case 0: goto L0; case 1: goto L1; case 2: goto L2; } L0: XSetSelectionOwner(display,latexdraw_selection,win,requesttime); if (XGetSelectionOwner(display,latexdraw_selection) != win) { protokoll("XGetSelectionOwner"," failed"); return 0;} freieselement(&relsel); wartendexport = true; kmark = 0; /*kmark, keine Objekte definiert */ export_relsel = relsel; export_kmark = kmark; strcpy(pr4, pr2menue[mcut]); return 1; L1: /*Referenzpunkt angeben*/ x1[relsel] = x; y1_[relsel] = y; x2[relsel] = x; y2[relsel] = y; strcpy(pr4," object(s)?"); return 2; L2: strcpy(pr4," object(s)?"); if (blinkelemente(xa,ya,xe,ye,1L)== false){ if (kmark==0) return 2; } else { /* Elemente in der bisherigen Sequenz muessen unveraendert bleiben */ for (elsel = 1; elsel <= zelmax; elsel++) { if (blink[elsel] == true) { /* schon vorhanden ? */ for (i=1;i <=kmark;i++) { if (sequenz[i] == elsel) goto LL; } kmark++; sequenz[kmark] = elsel; } LL:; } /*for*/ } blinkend = true; /*alle Blinkelemente wieder setzen */ for (i=1;i <= kmark;i++) blink[sequenz[i]] = true; export_kmark = kmark; return 2; } Static Void event_senden(r) long r; { XEvent sendevent; sendevent.xselection.type=selnotify[r].type; sendevent.xselection.requestor=selnotify[r].requestor; sendevent.xselection.selection=selnotify[r].selection; sendevent.xselection.target=selnotify[r].target; sendevent.xselection.property=selnotify[r].property; sendevent.xselection.time=selnotify[r].time; XSendEvent(display,selnotify[r].requestor,True,NoEventMask, &sendevent); } Static Void exportieren() { long r, kakt,relsel,i,kmark,ls1,ls2; char s1[255],s2[255]; if (selmenue[mcut]==false){ /* nichts geht mehr zurueck */ for (r=0;r selnotify[r].time) goto L0; goto L1; } } } /* Neueintrag in offene Requests */ for (r=0;ri;j--) { if (sequenz[j] < sequenz[i]) { kopunvotext(i,temp); kopunvotext(j,i); kopunvotext(temp,j); } } } typ[temp]=0; } Static long up(xanf,yanf,xend,yend,taste,msel,phase) long *msel,phase,taste; double xanf,yanf,xend,yend; {/* Elemente in Vordergrund bringen */ long elsel, maxnr; switch (phase){ case 0: goto L0; case 1: goto L1; } L0: return 1; L1: maxnr = zelmax; if (blinkelemente(xanf,yanf,xend,yend,1L)== false) return; vorbsortieren(); for (elsel=zelmax; elsel >= 1; elsel--) { if (blink[elsel] == true ) sequenz[elsel] = ++maxnr; } sortieren(); auselemente(); return 1; } /*end up*/ Static long down(xanf,yanf,xend,yend,taste,msel,phase) long *msel,phase,taste; double xanf,yanf,xend,yend; {/* Elemente in Vordergrund bringen */ long elsel, maxnr; switch (phase){ case 0: goto L0; case 1: goto L1; } L0: return 1; L1: maxnr = -zelmax-1; if (blinkelemente(xanf,yanf,xend,yend,1L)== false) return; vorbsortieren(); for (elsel=1;elsel<=zelmax; elsel++) { if (blink[elsel] ==true) sequenz[elsel] = ++maxnr; } sortieren(); auselemente(); return 1; } /*end up*/ Static Void elchangelineattr(elsel) long elsel; { long ltyp1, ldicke1, lende1, lcolor1; long ltyp2, ldicke2, lende2, lcolor2; getlineattribute(elsel, typ[elsel], <yp1, &ldicke1, &lende1, &lcolor1); ausel(elsel, erase); getlineattribute(0L, typ[elsel], <yp2, &ldicke2, &lende2, &lcolor2); if (changelende == true) lineende[elsel] = lende2; if ((changelstyle == true)&&(typ[elsel] != ttext)) linetype[elsel] = ltyp2; if (changelwidth == true) ldicke1 = ldicke2; if (changecolor == true) lcolor1 = lcolor2; linedicke[elsel] = 100*lcolor1+ldicke1; if ((typ[elsel] == ttext)&&(changefont == true)) { linetype[elsel] = fontnummer; textparam(elsel); berechneminmax(elsel); } if ((typ[elsel] == ttext)&&(changeposition == true)) setlagetext(elsel); zeichnen = true; } Static long changelineattr(xanf,yanf,xend,yend,taste,msel,phase) long *msel,phase,taste; double xanf,yanf,xend,yend; {/* Farbe Elemente veraendern*/ long elsel; switch (phase){ case 0: goto L0; case 1: goto L1; } L0: /* nur aendern, falls nach chatt entspr. Element angeklickt wurde*/ changelende = false; changelstyle = false; changelwidth = false; changecolor = false; changefont = false; changeposition = false; return 1; L1: if (blinkelemente(xanf,yanf,xend,yend,1L)==false) return 1; for (elsel=1; elsel <= zelmax; elsel++) { if (blink[elsel] == true) elchangelineattr(elsel); } /*for elsel*/ auselemente(); return 1; } /*end changelineattr*/ Static long queryattr(xanf,yanf,taste,msel,phase) long *msel,phase,taste; double xanf,yanf; {/* Farbe eines Elements erfragen und einstellen */ long elsel, ltyp, lende; switch (phase){ case 0: goto L0; case 1: goto L1; } L0: return 1; L1: if (blinkelemente(xanf,yanf,xend,yend,1L)== true) { for (elsel=1;elsel<=zelmax; elsel++) { if (blink[elsel] ==true){ getlineattribute(elsel, typ[elsel], <yp, &aktldicke, &lende, &aktcolor); strichsymbol(); ausmenueelement(mdick); colorsymbol(); ausmenueelement(mcolor); if (typ[elsel]==ttext) setzeakttextfont(elsel); return 1; } } } return 1; } /*end welchefarbe*/ Static Void spgp(xg, yg, dx, dy, xp, yp) double xg, yg, dx, dy, *xp, *yp; { double xs, ys; boolean g; /*Geradendefinition durch xg,yg,dx,dy*/ g = lot(xg, yg, dx, dy, *xp, *yp, &xs, &ys); *xp += 2.0 * (xs - *xp); *yp += 2.0 * (ys - *yp); } Static Void spg1(i, xg, yg, dx, dy) long i; double xg, yg, dx, dy; { spgp(xg, yg, dx, dy, &x1[i], &y1_[i]); } Static Void spg2(i, xg, yg, dx, dy) long i; double xg, yg, dx, dy; { spgp(xg, yg, dx, dy, &x2[i], &y2[i]); } Static Void spgb(i, xg, yg, dx, dy) long i; double xg, yg, dx, dy; { spgp(xg, yg, dx, dy, &xb1[i], &yb1[i]); spgp(xg, yg, dx, dy, &xb2[i], &yb2[i]); } Static Void spgell0(i, xg, yg, dx, dy) long i; double xg, yg, dx, dy; { double xl, yl, lx, ly; lx = laenge1[i]; ly = laenge2[i]; ell_xy(x1[i], y1_[i], lx, ly, crw[i], srw[i], lx, 0.0, &xl, &yl); spgp(xg, yg, dx, dy, &xl, &yl); /*gespiegelter Endpunkt x_Achse der Ellipse*/ spg1(i, xg, yg, dx, dy); setzewinkel(i, x1[i], y1_[i], xl, yl); } Static Void spgell(i, xg, yg, dx, dy) long i; double xg, yg, dx, dy; { spgell0(i, xg, yg, dx, dy); } Static Void spgellbogen(i, xg, yg, dx, dy) long i; double xg, yg, dx, dy; { double xm, ym, lx, ly, cr, sr; lx = laenge1[i]; ly = laenge2[i]; ftausch(&xb1[i], &xb2[i]); ftausch(&yb1[i], &yb2[i]); spgb(i, xg, yg, dx, dy); spgell0(i, xg, yg, dx, dy); xm = x1[i]; ym = y1_[i]; cr = crw[i]; sr = srw[i]; wanf[i] = winkelell(xm, ym, lx, ly, cr, sr, xb1[i], yb1[i]); wend[i] = winkelell(xm, ym, lx, ly, cr, sr, xb2[i], yb2[i]); ellanfendpunkt(i); } Static Void spgkbogen(i, xg, yg, dx, dy) long i; double xg, yg, dx, dy; { ftausch(&xb1[i], &xb2[i]); ftausch(&yb1[i], &yb2[i]); spgb(i, xg, yg, dx, dy); spg1(i, xg, yg, dx, dy); wanf[i] = winkelk(x1[i], y1_[i], xb1[i], yb1[i]); wend[i] = winkelk(x1[i], y1_[i], xb2[i], yb2[i]); } Static Void einelspiegeln(elsel, xg, yg, dx, dy) long elsel; double xg, yg, dx, dy; { long i; freieselement(&i); kopunv(elsel, i); switch (typ[i]) { case ttext: spg1(i, xg, yg, dx, dy); spg2(i, xg, yg, dx, dy); spgb(i, xg, yg, dx, dy); setzewinkel(i, xb1[i], yb1[i], xb2[i], yb2[i]); textparam(i); break; case tgerade: spg1(i, xg, yg, dx, dy); spg2(i, xg, yg, dx, dy); break; case trechteckgef: spg1(i, xg, yg, dx, dy); spg2(i, xg, yg, dx, dy); spgb(i, xg, yg, dx, dy); /*setzewinkel(i, x1[i], y1_[i], xb1[i], yb1[i]);*/ break; case tdreieckgef: case tviereckgef: spg1(i, xg, yg, dx, dy); spg2(i, xg, yg, dx, dy); spgb(i, xg, yg, dx, dy); break; case tkreis: case tkreisgef: spg1(i, xg, yg, dx, dy); break; case tkreisbogen: case tkreissektorgef: spgkbogen(i, xg, yg, dx, dy); break; case tell: case tellgef: spgell(i, xg, yg, dx, dy); break; case tellbogen: case tellsektorgef: spgellbogen(i, xg, yg, dx, dy); break; case tbezier: case tbeziergef: spg1(i, xg, yg, dx, dy); spg2(i, xg, yg, dx, dy); spgb(i, xg, yg, dx, dy); break; }/*case*/ bestimmeneuegruppe(i); if (duplikat(i)==false) { berechneminmax(i); ausel(i, paint); } } /*einelspiegeln*/ Static Void elspiegeln(xanf, yanf, xend, yend, xg, yg, dx, dy) double xanf, yanf, xend, yend, xg, yg, dx, dy; { long elsel; if (blinkelemente(xanf, yanf, xend, yend, 1L) == false ) return; gruppenumbenennen(); for (elsel=1;elsel <=zelmax;elsel++) { if (blink[elsel] == true) { einelspiegeln(elsel, xg, yg, dx, dy); } } unbenutztegruppenfreigeben(); } /*elspiegeln*/ Static long spiegeln(x,y,xanf,yanf,xend,yend,taste,msel,phase) long *msel,taste,phase; double x,y,xanf,yanf,xend,yend; { static long elselg; double xg, yg, dx, dy; switch (phase){ case 0: goto L0; case 1: goto L1; case 2: goto L2; } L0: strcpy(pr4, pr2menue[*msel]); return 1; L1: sucheelement((long)nurgerade, &elselg, xanf, yanf); if (elselg==0) return 1; strcpy(pr4,pr3menue[*msel]); return 2; L2: dx = x2[elselg] - x1[elselg]; dy = y2[elselg] - y1_[elselg]; xg = x1[elselg]; yg = y1_[elselg]; elspiegeln(xanf, yanf, xend, yend, xg, yg, dx, dy); return 2; } Static long einpolygon(x,y,taste,msel,phase) long *msel,taste,phase; double x,y; { double r, dwi, cd, sd, cwi, swi, xx1, yy1, xx2, yy2; static long elsel; long n, k, anz; switch (phase){ case 0: goto L0; case 1: goto L1; case 2: goto L2; default: goto L3; } L0: freieselement(&elsel); return 1; L1: x1[elsel] = x; y1_[elsel] = y; strcpy(pr3,nullstr); strcpy(pr4, pr3menue[*msel]); return 2; L2: r = ppabstand(x, y, x1[elsel], y1_[elsel]); if (r < 2.0) r = 2.0; laenge1[elsel]=r; L2B: if (selmenue[mverbunden]==true) strcpy(pr3, "(connected) "); else strcpy(pr3, nullstr); strcpy(pr4,nullstr); inittastaturtext(nullstr, " number of edges?",1L); return 3; L3: if (istnullstr(EinText) == true) goto L4; anz=sscanf(EinText,"%ld",&n); if ((anz!=1)|| (n == 0) || (n < 3)) goto L2B; r=laenge1[elsel]; dwi = pi / n; cd = cos(dwi); sd = sin(dwi); /*Anfang Winkel 0*/ cwi = 1.0; swi = 0.0; addtheorem(cd, sd, cd, sd, &cd, &sd); /*Winkel verdoppeln*/ xx1 = x1[elsel] + r * cwi; yy1 = y1_[elsel] + r * swi; for (k = 1; k <= n; k++) { addtheorem(cd, sd, cwi, swi, &cwi, &swi); xx2 = x1[elsel] + r * cwi; yy2 = y1_[elsel] + r * swi; if (selmenue[mverbunden]==true) createline(0L, x1[elsel], y1_[elsel], xx2, yy2); createline(0L, xx1, yy1, xx2, yy2); xx1 = xx2; yy1 = yy2; } L4: strcpy(pr3,nullstr); strcpy(pr4,pr2menue[*msel]); return 1; } /*Polygon*/ Static Void size_change(display,ix,iy) Display *display; long ix,iy; { double xmalt,ymalt,dxm,dym; ixzmax=ix; xzmax=ix; iyzmax=iy; yzmax= iy; xmalt = xmittelzei; ymalt = ymittelzei; xmittelzei = (xzmax - xgr) / 2.0 + xgr; ymittelzei = (yzmax - yprompt - 12.0) / 2.0 + yprompt + 12.0; setze_clip_bereiche(display); /* fuer readstdin vermerken, welche Skalierungen durchgef"uhrt wurden */ dxm = xmalt-xmittelzei; dym = ymalt-ymittelzei; readdxx = readdxx + dxm*(1.0-readf); readdyy = readdyy + dym*(1.0-readf); /* Ende dieser Vermerke */ } Static Void initmisc() { long i; xmittelzei = (xzmax - xgr) / 2.0 + xgr; ymittelzei = (yzmax - yprompt - 12.0) / 2.0 + yprompt + 12.0; fgradbo = pi / wh; fbograd = wh / pi; *nullstr = '\0'; strcpy(textausrichtung[0], "[bl]"); strcpy(textausrichtung[1],nullstr); strcpy(textausrichtung[2], "[br]"); strcpy(textausrichtung[3], "[b]"); strcpy(textausrichtung[4], "[tl]"); strcpy(textausrichtung[5], "[tr]"); strcpy(textausrichtung[6], "[t]"); strcpy(textausrichtung[7], "[l]"); strcpy(textausrichtung[8], "[r]"); } Static Void initcutpaste() { long i; wartendexport=false; requesttime = 0; lasteventtime = 0; for (i=0;i 1.1) ) goto weiter; /* kein Schnittpunkt */ } px = xx1 + dx * wwg; py = yy1 + dy * wwg; wwell = winkel0(px, py, lx, ly); /* w fuer Ellipse */ if (si_fabs(wwell - wanf[elsel]) < 0.1) wwell = wanf[elsel]; if (si_fabs(wwell - wend[elsel]) < 0.1) wwell = wend[elsel]; (*anz)++; wgerade[*anz] = wwg; well[*anz] = wwell; if ((typ[elsel] == tkreisbogen || typ[elsel] == tellbogen || typ[elsel] == tkreissektorgef || typ[elsel] == tellsektorgef) && (inwinkel(elsel, wwell)==false)) /* Punkt ist doch kein Schnittpunkt */ (*anz)--; weiter:; } /*for*/ } Static Void gell0schnittp(elselg,elsel,anz,wgerade,well,instrecke) long elselg, elsel, *anz; double *wgerade, *well; boolean instrecke; { double xx1, yy1, xx2, yy2; xx1 = x1[elselg]; yy1 = y1_[elselg]; xx2 = x2[elselg]; yy2 = y2[elselg]; gell00schnittp(xx1,yy1,xx2,yy2,elsel,anz,wgerade,well,instrecke); } Static Void testwawe(wp, wa, we, w) double wp, *wa, *we, w; { if (si_fabs(w - wp) <= 0.001) /* der Schnittpunkt ist so nahe am Anclickpunkt, dass eine */ /* Entscheidung sinnlos ist, bzw. der Schnittpunkt igoriert werden */ /* sollte, insbesondere im Zusammenhang von connect, wo */ /* Grenzpunkte als Clickpunkte verwendet werden. */ return; if ((w < wp) && (w > *wa)) *wa = w; if ((w > wp) && (w < *we)) *we = w; } Static Void testxyell(elsel, elsel1, xx1, yy1, wp, wa, we) long elsel, elsel1; double xx1, yy1, wp, *wa, *we; { double w1, w, xxp, yyp, xx, yy, xm1, ym1, lx1, ly1, cr1, sr1, xm, ym, lx, ly, cr, sr; ellpar(elsel, &xm, &ym, &lx, &ly, &cr, &sr); /*Bezugsellipse elselp*/ ellpar(elsel1, &xm1, &ym1, &lx1, &ly1, &cr1, &sr1); w1 = winkel0(xx1, yy1, lx1, ly1); ell_xy(xm1, ym1, lx1, ly1, cr1, sr1, xx1, yy1, &xxp, &yyp); /*testkreis(xxp,yyp,7.0);*/ if (inwinkel(elsel1, w1)==false) goto _L1; w = winkelell(xm, ym, lx, ly, cr, sr, xxp, yyp); /*testkreis(xxp,yyp,6.0);*/ if (inwinkel(elsel, w)==false) goto _L1; ellw_xy(xm, ym, lx, ly, cr, sr, w, &xx, &yy); /*testkreis(xx,yy,5.0);*/ if (ppabstand(xxp, yyp, xx, yy) > 5.0) goto _L1; /*testkreis(xx,yy,3.0);*/ testwawe(wp, wa, we, w); testwawe(wp, wa, we, w + wg); testwawe(wp, wa, we, w - wg); _L1: ; } Static Void ellellschnittp(elselp, elsel1, wp, wa, we) long elselp, elsel1; double *wp, *wa, *we; { long i, anz; terg x1erg; double xm1, ym1, lx1, ly1, cr1, sr1, xm, ym, lx, ly, cr, sr, qlv, axx, axy, ax0, ayx, ayy, ay0, bxx, byy, bx, by, bxy, b, c4, c3, c2, c1, c0, xx1, yy1; ellpar(elselp, &xm, &ym, &lx, &ly, &cr, &sr); ellpar(elsel1, &xm1, &ym1, &lx1, &ly1, &cr1, &sr1); qlv = ly1 / lx1; qlv *= qlv; axx = (cr * cr1 + sr * sr1) / lx; axy = (sr * cr1 - cr * sr1) / lx; ax0 = (cr * (xm1 - xm) + sr * (ym1 - ym)) / lx; ayx = (cr * sr1 - sr * cr1) / ly; ayy = (sr * sr1 + cr * cr1) / ly; ay0 = (sr * (xm - xm1) + cr * (ym1 - ym)) / ly; bxx = axx * axx + ayx * ayx; byy = axy * axy + ayy * ayy; bx = 2.0 * (axx * ax0 + ayx * ay0); by = 2.0 * (axy * ax0 + ayy * ay0); bxy = 2.0 * (axx * axy + ayx * ayy); b = ax0 * ax0 + ay0 * ay0 - 1.0; bxx -= qlv * byy; b += byy * ly1 * ly1; c4 = bxx * bxx + qlv * bxy * bxy; c3 = 2.0 * (bxx * bx + qlv * by * bxy); c2 = 2.0 * bxx * b + bx * bx + qlv * by * by - ly1 * ly1 * bxy * bxy; c1 = 2.0 * (bx * b - ly1 * ly1 * by * bxy); c0 = b * b - ly1 * ly1 * by * by; glvierterord(c4, c3, c2, c1, c0, &anz, x1erg); for (i = 1; i <= anz; i++) { xx1 = x1erg[i]; yy1 = xx1 / lx1; yy1 = 1.0 - yy1 * yy1; yy1 = sisqrt(1.0, yy1); if (yy1 >= 0.0) { yy1 = ly1 * yy1; testxyell(elselp, elsel1, xx1, yy1, *wp, wa, we); testxyell(elselp, elsel1, xx1, -yy1, *wp, wa, we); } } } Static boolean ellbozuklein(r, wa, we) double r, wa, we; { double dw; dw = we - wa; if (dw < 0.0) dw += wg; dw = r * dw * fgradbo; if (dw < 3.0) return true; else return false; } Static Void ellauftrennen(elselp, wa, we) long elselp; double wa, we; { long i; double lmax; if (laenge1[elselp] > laenge2[elselp]) lmax = laenge1[elselp]; else lmax = laenge2[elselp]; while (wa < 0.0) wa += wg; while (wa >= wg) wa -= wg; while (we < 0.0) we += wg; while (we >= wg) we -= wg; if (si_fabs(wanf[elselp] - wa) < 0.5) wa = wanf[elselp]; if (si_fabs(wend[elselp] - we) < 0.5) we = wend[elselp]; if (wa == wanf[elselp] && we == wend[elselp]) goto _L1; switch (typ[elselp]) { case tkreis: case tkreisgef: if (wa == we) goto _L1; ausel(elselp, erase); wanf[elselp] = we; wend[elselp] = wa; if (typ[elselp] == tkreis) typ[elselp] = tkreisbogen; else typ[elselp] = tkreissektorgef; kreisanfendpunkt(elselp); if (ellbozuklein(lmax, wanf[elselp], wend[elselp])==true) typ[elselp] = 0; else berechneminmax(elselp); ausel(elselp, paint); break; case tell: case tellgef: if (wa == we) goto _L1; ausel(elselp, erase); wanf[elselp] = we; wend[elselp] = wa; if (typ[elselp] == tell) typ[elselp] = tellbogen; else typ[elselp] = tellsektorgef; ellanfendpunkt(elselp); if (ellbozuklein(lmax, wanf[elselp], wend[elselp])==true) typ[elselp] = 0; else berechneminmax(elselp); ausel(elselp, paint); break; case tkreisbogen: case tellbogen: case tkreissektorgef: case tellsektorgef: ausel(elselp, erase); if ((wa != wanf[elselp]) & (ellbozuklein(lmax, wa, wanf[elselp])==false)) { freieselement(&i); kopunv(elselp, i); wend[i] = wa; ellanfendpunkt(i); berechneminmax(i); ausel(i, paint); } if ((we != wend[elselp]) & (ellbozuklein(lmax, we, wend[elselp])==false)) { freieselement(&i); kopunv(elselp, i); wanf[i] = we; ellanfendpunkt(i); berechneminmax(i); ausel(i, paint); } typ[elselp] = 0; break; }/*case*/ _L1: ; } Static Void ellgschnittp(elsel, elselg, wp, wa, we, instrecke) long elsel, elselg; double *wp, *wa, *we; boolean instrecke; { long i, anz; double w; terg wgerade, well; gell0schnittp(elselg, elsel, &anz, wgerade, well, instrecke); for (i = 1; i <= anz; i++) { w = well[i]; while (w > wg) w -= wg; while (w < 0.0) w += wg; testwawe(*wp, wa, we, w); testwawe(*wp, wa, we, w + wg); testwawe(*wp, wa, we, w - wg); } } Static Void ellgischnittp(elsel, i, xx1,yy1,xx2,yy2, wp,wa,we, instrecke) long elsel, i; double xx1,yy1,xx2,yy2,*wp, *wa, *we; boolean instrecke; { /* i ist freies Element, xx1, ... definieren Endpunkte einer Strecke */ /* mit der die Ellipse elsel geschnitten wird */ /* instrecke = true, dann muss der Schnittpunkt auch in der */ /* Strecke i liegen */ typ[i] = tgerade; x1[i] = xx1; y1_[i] = yy1; x2[i] = xx2; y2[i] = yy2; ellgschnittp(elsel, i, wp, wa, we, instrecke); typ[i] = -1; } Static Void ellschnittp(elselp, elsel, wp, wa, we, instrecke) long elselp, elsel; double *wp, *wa, *we; boolean instrecke; /* instrecke = true, dann muss der Schnittpunkt auch in der */ /* Strecke elsel liegen, falls elsel Strecke */ { long i, e; boolean sonderfall; /* fuer Schnittpunktberuecksichtigung in Strecken */ sonderfall = true; e = elsel; switch (typ[elsel]) { case ttext: break; case tgerade: ellgschnittp(elselp, elsel, wp, wa, we, instrecke); break; case tkreis: case tkreisgef: case tkreisbogen: case tell: case tellgef: case tellbogen: ellellschnittp(elselp, elsel, wp, wa, we); break; case tkreissektorgef: case tellsektorgef: freieselement(&i); ellellschnittp(elselp, elsel, wp, wa, we); ellgischnittp(elselp,i,x1[e],y1_[e],xb1[e],yb1[e],wp,wa,we,sonderfall); ellgischnittp(elselp,i,x1[e],y1_[e],xb2[e],yb2[e],wp,wa,we,sonderfall); break; case tdreieckgef: freieselement(&i); ellgischnittp(elselp,i,x1[e],y1_[e],x2[e],y2[e],wp,wa,we,sonderfall); ellgischnittp(elselp,i,x2[e],y2[e],xb1[e],yb1[e],wp,wa,we,sonderfall); ellgischnittp(elselp,i,xb1[e],yb1[e],x1[e],y1_[e],wp,wa,we,sonderfall); break; case trechteckgef: case tviereckgef: freieselement(&i); ellgischnittp(elselp,i,x1[e],y1_[e],xb1[e],yb1[e],wp,wa,we,sonderfall); ellgischnittp(elselp,i,xb1[e],yb1[e],x2[e],y2[e],wp,wa,we,sonderfall); ellgischnittp(elselp,i,x2[e],y2[e],xb2[e],yb2[e],wp,wa,we,sonderfall); ellgischnittp(elselp,i,xb2[e],yb2[e],x1[e],y1_[e],wp,wa,we,sonderfall); break; case tbezier: case tbeziergef: break; }/*case*/ } Static Void etrim(elselp, elsel1, elsel2, xp, yp, instrecke) long elselp, elsel1, elsel2; double xp, yp; boolean instrecke; { double xm, ym, lx, ly, cr, sr, wa, we, wp; ellpar(elselp, &xm, &ym, &lx, &ly, &cr, &sr); wp = winkelell(xm, ym, lx, ly, cr, sr, xp, yp); wa = wanf[elselp]; we = wend[elselp]; if (typ[elselp] == tkreis || typ[elselp] == tell || typ[elselp] == tkreisgef || typ[elselp] == tellgef) { wa -= wg; we += wg; } if (wp < wa) wp += wg; if (we <= wa) we += wg; ellschnittp(elselp, elsel1, &wp, &wa, &we, instrecke); if (elsel1 != elsel2) ellschnittp(elselp, elsel2, &wp, &wa, &we, instrecke); ellauftrennen(elselp, wa, we); } Static Void gellschnittp(elselp, elsel, wp, wa, we) long elselp, elsel; double *wp, *wa, *we; { double w; long anz, i; terg wg_, well; gell0schnittp(elselp, elsel, &anz, wg_, well, false); for (i = 1; i <= anz; i++) { w = wg_[i]; if (w > *wa && w < *we) { if (w < *wp) *wa = w; else *we = w; } } /*for i*/ } Static double winkelg(elsel, xp, yp) long elsel; double xp, yp; { double dx, dy; dx = x2[elsel] - x1[elsel]; dy = y2[elsel] - y1_[elsel]; if (si_fabs(dx) > si_fabs(dy)) return ((xp - x1[elsel]) / dx); else return ((yp - y1_[elsel]) / dy); } Static Void ggschnittp(elselp, elsel, wp, wa, we, instrecke) long elselp, elsel; double *wp, *wa, *we; boolean instrecke; { /* Schnittpunkt zweier Geraden, Schnittpunkt liegt in der durch */ /* elselp definierten Strecke. Falls instrecke true liegt der */ /* Schnittpunkt auch in der durch elsel definierten Strecke */ double dxp, dyp, dx, dy, xx1p, yy1p, xx1, yy1, n, z, vz, w; xx1p = x1[elselp]; yy1p = y1_[elselp]; dxp = x2[elselp] - xx1p; dyp = y2[elselp] - yy1p; xx1 = x1[elsel]; yy1 = y1_[elsel]; dx = x2[elsel] - xx1; dy = y2[elsel] - yy1; n = dxp * dy - dx * dyp; /*xs,ys sei Schnittpunkt, n = nenner bei */ /* Ausdruck fuer xs, n==0: parallel */ if (n == 0.0) goto L1; /* m = (xs-xx1p)/dxp = z/n */ vz = fsign(n); n = si_fabs(n); z = vz * (dy * (xx1 - xx1p) + dx * (yy1p - yy1)); if (z <= -0.01 || z >= 1.01*n) /* Schnittpunkt ausserhalb Strecke elselp */ goto L1; w = z / n; if (w <= *wa || w >= *we) goto L1; if (instrecke == true) { /* Test, ob Schnittpunkt auch in zweiter Strecke */ z = vz*(dyp*(xx1-xx1p)+dxp*(yy1p-yy1)); if ((z < -0.01)||(z > 1.01*n)) goto L1; } testwawe(*wp, wa, we, w); L1: ; } Static Void ggischnittp(elselg, i, xx1,yy1,xx2,yy2, wp,wa,we, instrecke) long elselg, i; double xx1,yy1,xx2,yy2,*wp, *wa, *we; boolean instrecke; { /* i ist freies Element, xx1, ... definieren Endpunkte einer Strecke */ /* mit der die Strecke elselg geschnitten wird */ /* instrecke = true, dann muss der Schnittpunkt auch in der */ /* Strecke i liegen */ typ[i] = tgerade; x1[i] = xx1; y1_[i] = yy1; x2[i] = xx2; y2[i] = yy2; ggschnittp(elselg, i, wp, wa, we, instrecke); typ[i] = -1; } Static Void gschnittp(elselg, elsel, wp, wa, we, instrecke) long elselg, elsel; double *wp, *wa, *we; boolean instrecke; { /* Bestimmung wa und we fuer Schnittpunkt auf Strecke elselg mit */ /* anderem Zeichnungselement elsel. Falls elsel eine Strecke und */ /* instrecke = true, dann muss der Schnittpunkt auch in der */ /* Strecke elsel liegen */ long i, e; boolean sonderfall; /* fuer Schnittpunkt in Strecke */ sonderfall = true; e = elsel; switch (typ[elsel]) { case ttext: break; case tgerade: ggschnittp(elselg, elsel, wp, wa, we, instrecke); break; case tkreis: case tkreisgef: case tkreisbogen: case tell: case tellgef: case tellbogen: gellschnittp(elselg, elsel, wp, wa, we); break; case tkreissektorgef: case tellsektorgef: freieselement(&i); gellschnittp(elselg, elsel, wp, wa, we); ggischnittp(elselg,i,x1[e],y1_[e],xb1[e],yb1[e],wp,wa,we,sonderfall); ggischnittp(elselg,i,x1[e],y1_[e],xb2[e],yb2[e],wp,wa,we,sonderfall); break; case tdreieckgef: freieselement(&i); ggischnittp(elselg,i,x1[e],y1_[e],x2[e],y2[e],wp,wa,we,sonderfall); ggischnittp(elselg,i,x2[e],y2[e],xb1[e],yb1[e],wp,wa,we,sonderfall); ggischnittp(elselg,i,xb1[e],yb1[e],x1[e],y1_[e],wp,wa,we,sonderfall); break; case trechteckgef: case tviereckgef: freieselement(&i); ggischnittp(elselg,i,x1[e],y1_[e],xb1[e],yb1[e],wp,wa,we,sonderfall); ggischnittp(elselg,i,xb1[e],yb1[e],x2[e],y2[e],wp,wa,we,sonderfall); ggischnittp(elselg,i,x2[e],y2[e],xb2[e],yb2[e],wp,wa,we,sonderfall); ggischnittp(elselg,i,xb2[e],yb2[e],x1[e],y1_[e],wp,wa,we,sonderfall); break; case tbezier: case tbeziergef: break; }/*case*/ } Static Void gauftrennen(elsel, wa, we) long elsel; double wa, we; { double xa, ya, xe, ye, xx1, yy1, xx2, yy2; ausel(elsel, erase); xx1 = x1[elsel]; yy1 = y1_[elsel]; xx2 = x2[elsel]; yy2 = y2[elsel]; xa = xx1 + (xx2 - xx1) * wa; ya = yy1 + (yy2 - yy1) * wa; xe = xx1 + (xx2 - xx1) * we; ye = yy1 + (yy2 - yy1) * we; if (wa == 0.0 && we == 1.0) /*beide Punkte bleiben*/ goto L1; if (wa == 0.0) { /*Punkt 2 bleibt*/ x1[elsel] = xe; y1_[elsel] = ye; goto L1; } if (we == 1.0) { /*Punkt 1 bleibt*/ x2[elsel] = xa; y2[elsel] = ya; goto L1; } /*Ausschnitt entfaellt*/ if (ppabstand(xx1, yy1, xa, ya) > 3) createline(elsel, xx1, yy1, xa, ya); x1[elsel] = xe; y1_[elsel] = ye; L1: /* connect davon abhaengig, dass altes Element verwendet wird */ if (ppabstand(x1[elsel], y1_[elsel], x2[elsel], y2[elsel]) > 3){ berechneminmax(elsel); ausel(elsel, paint); return; } typ[elsel] = 0; } Static Void gtrim(elselp, elsel1, elsel2, xp, yp, instrecke) long elselp, elsel1, elsel2; double xp, yp; { /* Trim mit der Geraden und nicht nur mit der Strecke, falls elsel1 */ /* oder elsel2 Strecken sind, falls instrecke = true */ double wa, we, wp; wa = 0.0; we = 1.0; wp = winkelg(elselp, xp, yp); if (wp > wa && wp < we) { gschnittp(elselp, elsel1, &wp, &wa, &we, instrecke); if (elsel1 != elsel2) gschnittp(elselp, elsel2, &wp, &wa, &we, instrecke); } gauftrennen(elselp, wa, we); } Static long trim(xa,ya,msel,phase) long *msel,phase; double xa,ya; { static long elselp, elsel1, elsel2, relsel; double xp,yp; switch (phase){ case 0: goto L0; case 1: goto L1; case 2: goto L2; case 3: goto L3; } L0: return 1; L1: sucheelement((long)nurtrimel, &elselp, xa, ya); if (elselp==0) return 1; freieselement(&relsel); x1[relsel] = xa; y1_[relsel] = ya; strcpy(pr4, " bounding object 1?"); return 2; L2: sucheelement((long)nurboundel, &elsel1, xa, ya); if ((elsel1==0)||(elsel1==elselp)) return 2; strcpy(pr4, " bounding object 2?"); return 3; L3: sucheelement((long)nurboundel, &elsel2, xa, ya); if ((elsel2==0)||(elsel2==elselp)) return 3; xp=x1[relsel]; yp=y1_[relsel]; switch (typ[elselp]) { case tgerade: gtrim(elselp, elsel1, elsel2, xp, yp, false); break; case tkreis: case tkreisgef: case tkreisbogen: case tkreissektorgef: etrim(elselp, elsel1, elsel2, xp, yp, false); break; case tell: case tellgef: case tellbogen: case tellsektorgef: etrim(elselp, elsel1, elsel2, xp, yp, false); break; }/*case*/ auselemente(); return 0; } /*trim*/ Static Void schwerpunkt(elsel,xs,ys) long elsel; double *xs,*ys; {/* Schwerpunkt Dreieck */ double dx1,dy1,dx2,dy2; dx1 = (x2[elsel]+xb1[elsel])/2.0-x1[elsel]; dy1 = (y2[elsel]+yb1[elsel])/2.0-y1_[elsel]; dx2 = (x1[elsel]+xb1[elsel])/2.0-x2[elsel]; dy2 = (y1_[elsel]+yb1[elsel])/2.0-y2[elsel]; *xs = (x1[elsel]*dy1*dx2-x2[elsel]*dy2*dx1+(y2[elsel]-y1_[elsel])*dx1*dx2) /(dy1*dx2-dy2*dx1); *ys = (*xs-x1[elsel])*dy1/dx1+y1_[elsel]; } Static Void fontwahl(taste) long taste; { selmenue[mfont] = false; if (taste==1) fontnummer = folgefont[fontnummer]; if (taste==3) fontnummer = prevfont[fontnummer]; strcpy(menue[mfont],textfontlabel[fontnummer]); ausmenueelement(mfont); } Static Void dickenwahl(taste) long taste; { selmenue[mdick]=false; ausmenueelement(mdick); if (taste==1) aktldicke = aktldicke +1; if (taste==3) aktldicke = aktldicke -1; if (aktldicke>maxldicke) aktldicke=1; if (aktldicke<1) aktldicke=maxldicke; strichsymbol(); ausmenueelement(mdick); } Static Void readzeitwahl(taste) long taste; { long f; f = 5; if (aktreadzeit < 50) f = 2; if (aktreadzeit < 20) f = 1; selmenue[mreadzeit]=false; if (taste==1) aktreadzeit += 1*f; if (taste==3) aktreadzeit -= 1*f; if (aktreadzeit>120) aktreadzeit = 120; if (aktreadzeit<0) aktreadzeit = 0; readzeitsymbol(); ausmenueelement(mreadzeit); } Static Void colorwahl(taste) long taste; { long posnr; /* Fortschaltung mit Farbnummern und nicht Positionsnummern */ posnr = aktcolor; /* posnr = farbposfarbnr[aktcolor]; */ selmenue[mcolor]=false; if (taste==1) posnr += 1; if (taste==3) posnr -= 1; if (posnr>=aktzahlfarben) posnr=0; if (posnr<0) posnr=aktzahlfarben-1; aktcolor = posnr; /* aktcolor = farbnrfarbpos[posnr]; */ colorsymbol(); ausmenueelement(mcolor); } Static Void somencolorwahl(i) long i; { aktcolor = farbnrfarbpos[i]; colorsymbol(); ausmenueelement(mcolor); } Static Void winkelsymbol() { Char sss[10]; sprintf(sss,"%3ld",winkelrotate); strcpy(menue[mwinkelrot],sss); } Static Void setwinkelrot(x) long x; { winkelrotate = x; winkelsymbol(); ausmenueelement(mwinkelrot); } Static Void winkelwahl(taste) long taste; { selmenue[mwinkelrot]=false; if (taste==1) winkelrotate += 5; if (taste==3) winkelrotate += 30; if (winkelrotate > 360) winkelrotate -= 360; winkelsymbol(); ausmenueelement(mwinkelrot); } Static long savedateien(msel,dateiname,taste,phase) Char *dateiname; long *msel,taste,phase; { long iphase; iphase = phase; switch (phase){ case 0: goto L0; case 100: goto L1; default: goto L2; } L0: inittastaturtext(dateiname,pr2menue[*msel],0L); return 100; L1: strcpy(dateiname, EinText); iphase = 0; L2: iphase = austexdatei(msel,dateiname,taste,iphase); if (iphase != 0) return iphase; iphase=schreibenausdatei(msel,dateiname,taste,iphase); selmenloeschen(msel); return 0; } Static long fuellen(x, y, msel, phase) long *msel,phase; double x, y; { static long i; long k; double xx1, yy1, xs, ys; switch (phase){ case 0: goto L0; case 1: goto L1; case 2: goto L2; } L0: vorbsortieren(); return 1; L1: sucheelement((long)nurfillel, &k, x, y); if (k == 0) return 1; freieselement(&i); kopunvotext(k,i); typ[i] = -1; switch (typ[k]) { case tgerade: xb1[i] = x; yb1[i] = y; strcpy(pr4, pr3menue[*msel]); return 2; case tkreis: typ[i] = tkreisgef; break; case tkreisbogen: typ[i] = tkreissektorgef; break; case tell: typ[i] = tellgef; break; case tellbogen: typ[i] = tellsektorgef; break; case tbezier: typ[i] = tbeziergef; break; } goto L4; L2: /* wird Dreieck oder Viereck */ sucheelement((long)nurgerade, &k, x, y); if (k == 0) return 2; xx1 = xb1[i]; yy1 = yb1[i]; typ[i]=tgerade; /* wenn Schnittpunkt, dann Dreieck */ if (gschnittpunkt(x1[i],y1_[i],x2[i]-x1[i],y2[i]-y1_[i], x1[k],y1_[k],x2[k]-x1[k],y2[k]-y1_[k], &xs, &ys) == true) { if ((inxystrecke(x1[i], y1_[i], x2[i], y2[i], xs, ys)== true)&& (inxystrecke(x1[k], y1_[k], x2[k], y2[k], xs, ys)== true)) { /*triangle*/ if (ppabstand(x1[i],y1_[i],xx1,yy1) > ppabstand(x1[i],y1_[i],xs,ys)) { x1[i] = x2[i]; y1_[i] = y2[i]; } x2[i] = xs; y2[i] = ys; xb1[i] = x1[k]; yb1[i] = y1_[k]; if (ppabstand(x1[k],y1_[k],x,y) > ppabstand(x1[k],y1_[k],xs,ys)) { xb1[i] = x2[k]; yb1[i] = y2[k]; } typ[i] = tdreieckgef; goto L3; } } /* Durch zwei Linien sind vier Punkte fuer ein Viereck (quadrangle) */ /* definiert. Da die zu verbindenden Punkte so noch nicht eindeutig */ /* definiert sind, wird vereinbart: Verbunden werden die beiden, dem */ /* jeweiligen Klickpunkt am naechsten liegenden Punkte */ if (ppabstand(x1[i],y1_[i],xx1,yy1) < ppabstand(x2[i],y2[i],xx1,yy1)) { xb1[i] = x1[i]; yb1[i] = y1_[i]; x1[i] = x2[i]; y1_[i] = y2[i]; } else { xb1[i] = x2[i]; yb1[i] = y2[i]; } if (ppabstand(x1[k],y1_[k],x,y) < ppabstand(x2[k],y2[k],x,y)) { x2[i] = x1[k]; y2[i] = y1_[k]; xb2[i] = x2[k]; yb2[i] = y2[k]; } else { x2[i] = x2[k]; y2[i] = y2[k]; xb2[i] = x1[k]; yb2[i] = y1_[k]; } typ[i] = tviereckgef; L3: berechneminmax(i); L4: setlineattribute(0L, i); sequenz[i]= -10; /*wird erstes Element */ sortieren(); auselemente(); return 0; } /* end of fuellen */ Static long showgroup(xanf,yanf,taste,msel,phase) double xanf,yanf; long taste, *msel,phase; { long elsel; switch (phase){ case 0: goto L0; case 1: goto L1; } L0: return 1; L1: sucheelement((long)alleelem, &elsel, xanf, yanf); if (elsel != 0) { blinkenan(); initgruppentag(false); blinkgruppe(elsel); } return 1; } Static long newgroup(xanf,yanf,xend,yend,taste,msel,phase) double xanf,yanf,xend,yend; long taste, *msel,phase; { long i,elsel,gelsel,gi; static long wurzel; switch (phase){ case 0: goto L0; case 1: goto L1; } L0: wurzel = 0; /* alte Markierungen loeschen, da spaeter sonst verwertet */ for (i=1;i<=zelmax;i++) blink[i] = false; return 1; L1: if (blinkelemente(xanf, yanf, xend, yend, 1L)==false) goto L0B; if (wurzel == 0) { /* alle bisher selektierten Elemente kennzeichen */ for (i=1;i<=zelmax;i++) blink[i] = blink[i] || blinkalt[i]; /* Pruefen ob mindestens zwei verschiedene Gruppen */ elsel = 0; for (i=1;i<=zelmax;i++) { if ( (typ[i]>0)&&(blink[i]==true) ) { if (elsel == 0) { elsel = i; gelsel = group[elsel]; } else { gi = group[i]; if ( (gi == 0) || (gelsel == 0) || (gruppenwurzel(i) != gruppenwurzel(elsel)) ) { /* zwei Gruppen */ wurzel = freiegruppe(); break; } } } } }/* end if wurzel == 0 */ if (wurzel == 0) { /* nichts zu gruppieren */ goto L0B; } /* Neue Gruppe da und evtl. Elemente zu gruppieren */ for (i=1;i<=zelmax;i++) { if ( (typ[i]>0)&&(blink[i]==true)&& (gruppenwurzel(i) != wurzel) ){/* zufuegen */ gruppieren(i, wurzel); } } L0B: /* alle bisher selektierten Elemente kennzeichen */ for (i=1;i<=zelmax;i++) { blink[i] = blink[i] || blinkalt[i]; if (blink[i] == true) blinkend = true; } return 1; } Static long ungroup(xanf,yanf,taste,msel,phase) double xanf,yanf; long taste, *msel,phase; { static long elsel; long g; switch (phase){ case 0: goto L0; case 1: goto L1; case 2: goto L2; } L0: elsel = 0; return 1; L1: sucheelement((long)alleelem, &elsel, xanf, yanf); if (elsel != 0) { blinkenan(); initgruppentag(false); blinkgruppe(elsel); } return 1; L2: /* bei OK gedrueckt */ if (elsel==0) return 0; loeschegruppe(elsel); blinkenan(); initgruppentag(false); blinkgruppe(elsel); return 1; } Static long groupok(msel, phase) long *msel, phase; { selmenue[mgroupok]=false; ausmenueelement(mgroupok); if (*msel==mungroup) return ungroup(0.0, 0.0, 1, msel,2); return phase; } Static Void connectpunkt(elsel, xa, ya, xc, yc) long elsel; double xa, ya, *xc, *yc; { long e; switch (typ[elsel]) { case ttext: case tkreis : case tkreisgef: case tkreisbogen: case tell: case tellgef: case tellbogen: case tkreissektorgef: case tellsektorgef: *xc = x1[elsel]; *yc = y1_[elsel]; return; case tgerade: case trechteckgef: *xc = (x1[elsel]+x2[elsel])*0.5; *yc = (y1_[elsel]+y2[elsel])*0.5; return; case tviereckgef: e = elsel; if (gschnittpunkt(x1[e],y1_[e],xb2[e]-x1[e],yb2[e]-y1_[e], x2[e],y2[e], xb1[e]-x2[e],yb1[e]-y2[e], xc, yc) == true) { if ((inxystrecke(x1[e],y1_[e],xb2[e],yb2[e], *xc,*yc)== true)&& (inxystrecke(x2[e],y2[e], xb1[e],yb1[e], *xc,*yc)== true)) { return; } } if (gschnittpunkt(x1[e],y1_[e],xb1[e]-x1[e],yb1[e]-y1_[e], x2[e],y2[e], xb2[e]-x2[e],yb2[e]-y2[e], xc, yc) == true) { if ((inxystrecke(x1[e],y1_[e],xb1[e],yb1[e], *xc,*yc)== true)&& (inxystrecke(x2[e],y2[e], xb2[e],yb2[e], *xc,*yc)== true)) { return; } } *xc = (x1[elsel]+x2[elsel])*0.5; *yc = (y1_[elsel]+y2[elsel])*0.5; return; case tdreieckgef: schwerpunkt(elsel,xc,yc); return; case tbezier: case tbeziergef: if (ppabstand(xa,ya,x1[elsel],y1_[elsel]) <= ppabstand(xa,ya,x2[elsel],y2[elsel])) { *xc = x1[elsel]; *yc = y1_[elsel]; } else { *xc = x2[elsel]; *yc = y2[elsel]; } return; } } Static Void conngschnittp(elselg, elsel, wp, wa, we) long elselg, elsel; double *wp, *wa, *we; { /* Trimmen der durch elselg bezeichneten Strecke mit elsel fuer */ /* connect. Der Schnittpunkt ist nur relevant, falls er bei Strecken */ /* in beiden Strecken liegt. Deshalb true beim Aufruf von gschnittp. */ *wa = 0.0; *we = 1.0; if (elsel == 0) return; /*nichts zu trimmen!*/ switch (typ[elsel]) { case ttext: break; case tgerade: case tkreis : case tkreisgef: case tkreisbogen: case tell: case tellgef: case tellbogen: case tkreissektorgef: case tellsektorgef: case tdreieckgef: case trechteckgef: case tviereckgef: gschnittp(elselg, elsel, wp, wa, we, true); break; case tbezier: case tbeziergef: break; }/*of switch */ } Static Void conntrim(art, elselg, elsel1, elsel2) long art, elselg, elsel1, elsel2; { /* Trimmen fuer connect, erst mit elsel1, dann mit elsel2. Der */ /* Schnittpunkt ist nur relevant, falls er bei Strecken in beiden */ /* Strecken liegt. Deshalb true beim Aufruf. */ double wa, we, wp; switch (art) { case 1: wp = 0.0; conngschnittp(elselg, elsel1, &wp, &wa, &we, true); break; case 2: wp = 1.0; conngschnittp(elselg, elsel2, &wp, &wa, &we, true); break; case 3: wp = 0.0; conngschnittp(elselg, elsel1, &wp, &wa, &we, true); gauftrennen(elselg, wa, we); if (typ[elselg] == 0) return; wp = 1.0; conngschnittp(elselg, elsel2, &wp, &wa, &we, true); break; } gauftrennen(elselg, wa, we); } Static long connect(xs,ys,xa,ya,taste,msel,phase) double xs,ys,xa,ya; long taste,phase,*msel; {/* Verbindung zweier Elemente */ static long elsel1,elsel2, relsel; long i1,i2; double xc1,yc1,xc2,yc2; switch (phase){ case 0: goto L0; case 1: goto L1; case 2: goto L2; } L0: return 1; L1: sucheelement((long)alleelem, &elsel1, xa, ya); if (elsel1 == 0) return 1; freieselement(&relsel); connectpunkt(elsel1, xa, ya, &xc1, &yc1); x1[relsel] = xc1; y1_[relsel] = yc1; strcpy(pr4, pr3menue[*msel]); return 2; L2: if (selmenue[mconnpoint] == false) {/*zweites Objekt gegeben*/ sucheelement((long)alleelem, &elsel2, xa, ya); if ((elsel2 == 0)|| (elsel2 == elsel1)) return 2; connectpunkt(elsel2, xa, ya, &xc2, &yc2); } else {/*Punkt anstelle eines zweiten Objekts */ xc2 = xs; yc2 = ys; elsel2 = 0L; } xc1 = x1[relsel]; yc1 = y1_[relsel]; if (selmenue[mconnxy] == true) { i1 = interncreateline(0L, xc1,yc1,xc2,yc1); i2 = interncreateline(0L, xc2,yc1,xc2,yc2); goto L3; } if (selmenue[mconnyx] == true) { i1 = interncreateline(0L, xc1,yc1,xc1,yc2); i2 = interncreateline(0L, xc1,yc2,xc2,yc2); goto L3; } /* direkte Verbindung */ i1 = interncreateline(0L, xc1,yc1,xc2,yc2); if (i1 == 0) return 0; conntrim(3,i1, elsel1, elsel2); return 0; L3: if ((i1 == 0) && (i2 == 0)) return 0; if (i1 == 0) { conntrim(3,i2, elsel1, elsel2); return 0; } if (i2 == 0) { conntrim(3,i1, elsel1, elsel2); return 0; } lineende[i1] = 0L; lineende[i2] = 0L; if (selmenue[mcapprojecting] == true) { lineende[i1] = 4L; lineende[i2] = 4L; } if (selmenue[mpfeilanf] == true) lineende[i1] = 1L; if (selmenue[mpfeilende] == true) lineende[i2] = 2L; conntrim(1,i1, elsel1, elsel2); conntrim(2,i2, elsel1, elsel2); return 0; } Static long readstdin(msel,phase) long phase,*msel; { long i,j,k,anz; double xxmin,xxmax,yymin,yymax; switch (readphase) { case 0: /* erster Aufruf */ readphase = 1; case 1: /* evtl. kommt jetzt Vorspann */ if (geteingabezeile(stdin)==0) return readphase; /* Vorspann lesen, falls da */ if (NULL != strstr(eingabezeile,"LaTeXdraw (Siegert, TUM, C")) { /* es kommt epc-Vorspann */ readphase = 2; } else { /* es kommen nur Zeichnungselemente */ readphase = 6; } return readphase; case 2: /* es beginnt neue Zeichnung, loesche alte Elemente !!*/ for (i = 1; i <= zelmax; i++) typ[i] = 0; kompakt(); /* EPC-Vorspann lesen, erste Zeile schon da */ einvorspannepc(stdin); readphase = 3; return readphase; case 3: /* einzelne Zeichnungslemente lesen */ anz = geteingabezeile(stdin); if (anz == 0) fehler(3L); anz=einlesenelement(stdin,&i); if (typ[i] == 0) { /* das ist das Ende eines Bildes, es kommt noch Gruppeninformation */ readphase = 4; } else skalieren(i,readdxx,readdyy,readf); return readphase; case 4: /* Gruppeninformation kommt */ if (version >= 13.0) /* Gruppen sind da!*/ eindateigruppen(stdin); if (version < 11.0) { minmax(&xxmin,&xxmax,&yymin,&yymax); breite=(xxmax-xxmin)*texfaktor; hoehe=(yymax-yymin)*texfaktor; } ausfastalles(); readphase = 1; if (aktreadzeit != 0) ltd_usleep(aktreadzeit,0L); /* readzeit Sekunden warten */ return readphase; case 5: /* Zeichnungselement, wenn nur Zeichnungslemente */ anz = geteingabezeile(stdin); if (anz == 0) fehler(3L); case 6: readphase = 5; anz=einlesenelement(stdin,&i); if (typ[i] == 0) { /* das ist das Ende eines Bildes, es kommt */ /* ggf. neues Bild oder weitere Elemente */ readphase = 1; kompakt(); ausfastalles(); if (aktreadzeit != 0) ltd_usleep(aktreadzeit,0L); /* readzeit Sekunden warten */ return readphase; } /*Zeichnungselement gelesen */ skalieren(i,readdxx,readdyy,readf); if (typ[i] < 0) { /* entsprechendes Element loeschen, falls da */ typ[i] = -typ[i]; if ( (j=duplikat0(i,true))!=0 ) loescheelement(j); loescheelement(i); } else { if ( (j = duplikat0(i,false))!=0 ) { lineende[j] = lineende[i]; linedicke[j] = linedicke[i]; linetype[j] = linetype[i]; loescheelement(i); } } kompakt(); return readphase; }/* end of switch */ } /* diese Prozedur wird als Thread ausgefuehrt !!!!! */ /* kein Zugriff auf Display in dieser Prozedur */ Static void* threadreadstdin(vpar) void *vpar; { /* threadaktiv und threadausel sind globale Variable*/ /* threadausel == 1 signalisiert der Umgebung, dass */ /* eingelesene Zeichnungselemente ausgegeben werden sollen */ /* Abfrage in Schleife bevor auf Event geprueft wird */ long i,j,k,anz; double xxmin,xxmax,yymin,yymax; while (1) { if (aktreadzeit != 0) ltd_usleep(aktreadzeit,0L); /* grundsaetzlich readzeit Sekunden warten */ while (threadaktiv==0){ ltd_usleep(5L,0L); } /* jetzt versuchen zu lesen */ /* evtl. kommt jetzt Vorspann */ while (geteingabezeile(stdin)==0) {}; /* Vorspann lesen, falls da */ if (NULL == strstr(eingabezeile,"LaTeXdraw (Siegert, TUM, C")) { /* es kommen nur Zeichnungselemente */ goto einzelelemente; } /* es kommt epc-Vorspann */ /* es beginnt neue Zeichnung, loesche alte Elemente !!*/ for (i = 1; i <= zelmax; i++) typ[i] = 0; kompakt(); /* EPC-Vorspann lesen, erste Zeile schon da */ einvorspannepc(stdin); while (1) { /* einzelne Zeichnungslemente lesen */ anz = geteingabezeile(stdin); if (anz == 0) fehler(3L); anz=einlesenelement(stdin,&i); if (typ[i] == 0) { /* das ist das Ende eines Bildes, es kommt noch Gruppeninformation */ goto gruppeninformation; } skalieren(i,readdxx,readdyy,readf); } gruppeninformation: /* Gruppeninformation kommt */ if (version >= 13.0) /* Gruppen sind da!*/ eindateigruppen(stdin); if (version < 11.0) { minmax(&xxmin,&xxmax,&yymin,&yymax); breite=(xxmax-xxmin)*texfaktor; hoehe=(yymax-yymin)*texfaktor; } threadausel=1; continue; einzelelemente: anz=einlesenelement(stdin,&i); if (typ[i] == 0) { /* das ist das Ende eines Bildes, es kommt */ /* ggf. neues Bild oder weitere Elemente */ } else { /*Zeichnungselement gelesen */ skalieren(i,readdxx,readdyy,readf); if (typ[i] < 0) { /* entsprechendes Element loeschen, falls da */ typ[i] = -typ[i]; if ( (j=duplikat0(i,true))!=0 ) loescheelement(j); loescheelement(i); } else { if ( (j = duplikat0(i,false))!=0 ) { lineende[j] = lineende[i]; linedicke[j] = linedicke[i]; linetype[j] = linetype[i]; loescheelement(i); } } } threadausel=1; }/* while (1) wird von thread nicht verlassen */ } Static long aktion(msel,xs,ys,xa,ya,xe,ye,taste,phase) double xs,ys,xa,ya,xe,ye; long taste,phase,*msel; { long i, elsel; LA: XDefineCursor(display,win,busycursor); LM: if (taste==0) goto LZ; /*es erfolgte eine Tastatureingabe*/ if ((xa < xgr) && (koordinateneingegeben==false)) { /*x in Menuebereich */ if (xa<=xgrf) { i=somenbesti(xa,ya); if (i < 0) return phase; if (i0)&&(xzmax<2000)&&(yzmax>0)&&(yzmax<2000)) { xzmax0 = xzmax; yzmax0 = yzmax; } } if ((strvergl(argv[iv],"-io")==true)&&((iv+2) < argc)) { nur_texausgabe=true; /* nur LaTex-Ausgabedatei erzeugen!! */ strcpy(dateiname,argv[iv+1]); /* Name LaTexDraw-Eingabedatei */ strcpy(texdateiname,argv[iv+2]); /* Name LaTex-Ausgabedatei */ } } init_tmenue(); if (( display = XOpenDisplay(display_name))== NULL) fehler(6); screen = DefaultScreen(display); nocolors = false; /* Farben verfuegbar */ if (DisplayPlanes(display,screen)<=2) /*monochrom oder wenige Graustufen*/ nocolors = true; initfarbnamen(); init_window_font(display); win = XCreateSimpleWindow( display,RootWindow(display,screen),0,0,ixzmax,iyzmax,4, BlackPixel(display,screen), WhitePixel(display,screen)); initfarben(screen, display, win); reihenfolgefarben(); initGC(screen, display, win); setze_clip_bereiche(display); size_hints.flags = PPosition | PSize ; size_hints.x = 0; size_hints.y = 0; size_hints.width = ixzmax; size_hints.height = iyzmax; XSetStandardProperties(display,win,window_name,icon_name,None, argv,argc,&size_hints); XSelectInput(display,win,ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | StructureNotifyMask | Button1MotionMask); clickcursor=XCreateFontCursor(display,XC_left_ptr); busycursor=XCreateFontCursor(display,XC_heart); textcursor=XCreateFontCursor(display,XC_dotbox); if (nur_texausgabe == false) XMapWindow(display,win); XSetInputFocus(display,PointerRoot,RevertToPointerRoot,CurrentTime); XSetErrorHandler(myerrorhandler); geoeffnet=0; init_kmenue(); initmisc(); initcutpaste(); #ifdef TABLETT /* Falls ein Digitizer angeschlossen ist, initialisieren */ if (tablett) { if (init_digitizer(display) == -1) fehler(18); } #endif msel = 0; datdeskr = NULL; erwartet=click_erwartet; winerwartet = 0; phase=0; if (nur_texausgabe == false) strcpy(dateiname,nullstr); curs_x = -100.0; curs_y = -100.0; LNEU: init_neuezeichnung(); xlast=0.0; ylast=0.0; for (i = 1; i <= zmenue; i++) selmenue[i] = false; selmenue[msel] = true; selmenue[meinrasten] = true; selmenue[mltext] = true; selmenue[mbtext] = true; selmenue[mgroupmode] = true; strcpy(pr1, "select/ "); strcpy(pr2, menue[msel]); strcpy(pr3, nullstr); strcpy(pr4, nullstr); strcpy(pr5, nullstr); strcpy(pr6, nullstr); taste=0; button1gedrueckt =0; button2gedrueckt =0; button3gedrueckt =0; controlan = 0; blinkend = false; koordinateneingegeben=false; dragbox=0; setwinkelrot(90); if (nur_texausgabe == true) { /* nur Erzeugung der LaTeX-Ausgabedatei */ /* Option -io bei Aufruf von latexdraw */ taste = 0; msel = mladen; phase = 2; eindatei(&msel,dateiname,taste,phase); msel = msave; phase = 7; austexdatei(&msel,dateiname,taste,phase); schluss(0); } /* Event-Schleife */ while (1) { if (geoeffnet==1) { if (phase==0) { strcpy(pr1,"select/"); strcpy(pr2,nullstr); strcpy(pr3,nullstr); strcpy(pr4,nullstr); strcpy(pr5,nullstr); strcpy(pr6,nullstr); if (msel != 0) { strcpy(pr1, "select/ "); strcpy(pr2, menue[msel]); strcpy(pr4, pr2menue[msel]); } } prompt(); if (erwartet==click_erwartet) XDefineCursor(display,win,clickcursor); else { XDefineCursor(display,win,textcursor); cursan(curs_x,curs_y); } } if ((blinkend==true)&&(geoeffnet==1)) { while ( (int)XEventsQueued(display, QueuedAfterFlush) == 0) { #ifdef TABLETT if (tablett) process_digitizer(display, win); #endif ausblinkelemente(); } /* folgende zwei Befehle, damit nach Klick die Elemente */ /* ggf. sofort wieder geloescht dargestellt werden */ blinkfarbe = erase; blinkintervallzaehler = 0; } /* Eingabe ueber digitizer oder STDIN, solange kein X-Event */ while ( (int)XEventsQueued(display, QueuedAfterFlush) == 0) { #ifdef TABLETT if (tablett) { process_digitizer(display, win); } #endif #ifdef THREAD if (threadausel==1) { threadausel=0; kompakt(); ausfastalles(); /* nachfolgendes sleep kleiner als sleep in thread (derzeit Sekunden) */ /* sonst geht Abfrage von threadausel nicht */ } #endif #ifndef THREAD if (msel == mread) { phase = readstdin(&msel,phase); } #endif ltd_usleep(0L,30000); /* 30 ms Wartezeit */ } XNextEvent(display, &report); if (dragbox==1) xorrechteck(xanf,yanf,xend,yend); dragbox=0; switch (report.type) { case Expose: geoeffnet = 1; /* weitere vorhandene Expose-Events ignorieren */ while (XCheckTypedEvent(display,Expose,&report)) ; ausalles(); break; case ConfigureNotify: #ifdef TABLETT if (tablett) save_win_pos(report.xconfigure.x, report.xconfigure.y, report.xconfigure.width,report.xconfigure.height); #endif size_change(display, report.xconfigure.width,report.xconfigure.height); break; case ButtonPress: if (report.xbutton.button==button1) button1gedrueckt=1; if (report.xbutton.button==button2) button2gedrueckt=1; if (report.xbutton.button==button3) button3gedrueckt=1; taste=0; if (button1gedrueckt==1) taste = 1; if (button2gedrueckt==1) taste = 10*taste+2; if (button3gedrueckt==1) taste = 10*taste+3; getweltkoord(&xanf,&yanf); xend=xanf; yend=yanf; break; case MotionNotify: while (XCheckMaskEvent(display,Button1MotionMask,&report)); if (erwartet != click_erwartet) break; if (button1gedrueckt==0) break; if (!XQueryPointer(display, win, &rootwin, &childwin, &irootx, &irooty,&iwinx, &iwiny, &keysbuttons)) break; getmotionweltkoord(iwinx, iwiny, &xsnap, &ysnap); if ((dragbox == 1)&&(si_iabs(xsnap-xend) < 2)&& (si_iabs(ysnap-yend) < 2)) break; xend = xsnap; yend = ysnap; xorrechteck(xanf,yanf,xend,yend); dragbox=1; break; case ButtonRelease: if (report.xbutton.button==button1) button1gedrueckt=0; if (report.xbutton.button==button2) button2gedrueckt=0; if (report.xbutton.button==button3) button3gedrueckt=0; lasteventtime=report.xbutton.time; getweltkoord(&xend,¥d); if (xanf15.0)||(si_fabs(yanf-yend)>15.0)) { if (si_fabs(xanf-xend) > si_fabs(yanf-yend)) { /*horizontaler Strich, also horizontale Ausrichtung*/ if (si_fabs(xanf-xend)>15.0) ysnap=ylast; /*Ausrichtung Punkt */ } else { /*vertikaler Strich, also vertikale Ausrichtung*/ if (si_fabs(yanf-yend)>15.0) xsnap=xlast; /*Ausrichtung Punkt */ } } xlast=xsnap; ylast=ysnap; neueclickmarke(xsnap,ysnap); if ((si_fabs(xanf-xend)<5.0)||(si_fabs(yanf-yend)<5.0)){ xend=xanf; yend=yanf; } phase = aktion(&msel,xsnap,ysnap,xanf,yanf,xend,yend,taste,phase); break; case KeyPress: taste=XLookupString(&report.xkey,symstr,maxstrl,&keysym,&compose); if (keysym==NoSymbol) break; taste= keysym; control(taste, 1L); if (erwartet != tastatur_erwartet) {/* Sondertasten */ if ( (msel==mloeschen)&& ((taste==tastebackspace)|| (taste==tasteundo)||(taste == tastedelete)) ) { /*loeschen ist aktiv, backspace bedeutet undo*/ UnDelete(); phase = 1; } sondertaste (taste); break; } if (tastaturtext(taste)!=0) break; taste = 0; if (selmenue[mxytastatur]==true) { phasexyein = xyein(&xsnap, &ysnap,taste,phasexyein); xanf=xsnap; yanf=ysnap; xend=xsnap; yend=ysnap; neueclickmarke(xsnap,ysnap); taste = 1; koordinateneingegeben=true; /* initialisierung in aktion ! */ } phase = aktion(&msel,xsnap,ysnap,xanf,yanf,xend,yend,taste,phase); break; case KeyRelease: taste=XLookupString(&report.xkey,symstr,maxstrl,&keysym,&compose); if (keysym==NoSymbol) break; taste= keysym; control(taste, 0L); break; case SelectionClear: if (selmenue[mcut] == true) {selmenloeschen(&msel); exportieren();} break; case SelectionNotify: importieren(report.xselection.property,report.xselection.time,&msel); break; case SelectionRequest: request_export(report.xselectionrequest.requestor, report.xselectionrequest.property, report.xselectionrequest.target, report.xselectionrequest.time); break; } /* of case */ if (wartendexport==true) exportieren(); } /*end of while Event*/ } /* End. */