PROGRAM SLDToDXB;				{ (c) 1991 by URBAN Reinhard }
{ Converts AutoCAD Slides to AutoCAD DXB Files

Disclaimer
----------
   Copyright (C) 1995 Reini Urban
   All rights reserved world-wide.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

   Permission to use, copy, modify, and distribute this software
   for any purpose and without fee is hereby granted, provided
   that the above copyright notice appears in all copies and that
   both that copyright notice and this permission notice appear in
   all supporting documentation.

   Forbidden to be used for commercial purposes.

   COMMERCIAL SALE
   Any  software dealer or library may offer this software for sale,
   as long as the fees charged do not exceed  the  media  (diskette,
   CD-ROM) and copying costs, as long as I (the author) get a free
   copy of the medium.

Author:
   Reini Urban,  <rurban@sbox.tu-graz.ac.at>
   <A HREF="http://www.tu-graz.ac.at/Urban">Reini Urban</A>
*****************************************************************************

  Converts AutoCAD Slides to AutoCAD DXB Files
  (drawing exchange binary format)

  Accepts the old (pre Release 9.0) and the new slide format
  (post Release 9.0).

  Useful for:
  -----------
  Automatic conversion of view to block.
  Stores hidden line pictures as blocks, so that you dont have to
  recalculate the hidden lines at plotting time again, with keeping
  the color - and therefore the line thickness - information.
  (in comparison to plotting to DXB)
  With the right flag in the ACAD.PGP file DXB files are automatically
  inserted as blocks.
----------------------------------------------------------------------------

  Vorschlag zur Verwendung in AutoCAD:
  Diese Programm wurde erstellt, um VERDECKT gerechnete Zeichnungen nicht
  zweimal zu berechnen, das erste mal zur Kontrolle, und das zweite mal beim
  Plotten.
  Es wird also ein Dia erzeugt, das in eine DXB Datei konvertiert wird,
  und von AutoCAD automatisch als Block in die Zeichnung geladen wird.
  Als Block deswegen, weil dann die berechnete Perspektive als ganzes
  beliebig positioniert und skaliert werden kann.
  Der Befehls SLDDXB muá in die Datei ACAD.PGP eingefgt werden
  und ein Menue-Makro, ein SCRIPT oder ein AutoLISP Programm
  kann erstellt werden.

  Vorschlag fr ACAD.PGP:
    SLDDXB,\acad\slddxb,200000,*Konvertiere Dia in DXB: ,4

  in AutoCAD ber die Befehlsfolge:
    MACHDIA "name"
    SLDDXB "name"
    DXBIN "name"
}

{$N+}			{ IEEE Gleitkommazahlen }
{$ifopt R+} {$define Rangecheck} {$else} {$undef Rangecheck} {$endif}
USES Dos;

CONST
  DXB_Header : ARRAY [1..19] of char
    = ('A','u','t','o','C','A','D',' ','D','X','B',' ','1','.','0', #13,#10,#26,#0);

TYPE
  DXB_n_type = double;		{ Number Mode 1 }
  DXB_w_type = integer; 	{ Ganzkommazahl mit Vorzeichen }

CONST
  nl = sizeof (DXB_n_type);

VAR
  SLDFile	: FILE; 	{ untypisiert fr BlockRead/Write }
  DXBFile	: FILE;
  bSwap 	: boolean;	{ false bei 80x86 integer Typ
				  true bei 68000 integer Typ }
  ax, ay	: double;

PROCEDURE Error (s : STRING);
  BEGIN
    WriteLn (#7'Fehler: '+s);
    Halt (1);
  END;

FUNCTION max (i1, i2 : integer) : integer;
  BEGIN
  IF i1 >= i2
    THEN max := i1
    ELSE max := i2;
  END;

PROCEDURE Init;
{ analysiere DOS Parameter, ”ffne Dateien }
  VAR
    SldName, DXBName : PathStr;
    dir : DirStr;
    n1, n2 : NameStr;
    ext : ExtStr;
  BEGIN
    WriteLn;
    WriteLn ('AutoCAD Slide-DXB Konverter                       (c) URBAN Reinhard, Graz 1991');
    IF (ParamCount > 1)
     AND (
	   (ParamStr(1) = '/?') OR
	   (ParamStr(1) = '?') OR
	   (ParamStr(1) = '/h') OR
	   (ParamStr(1) = '/H') OR
	   (ParamStr(1) = '-?') OR
	   (ParamStr(1) = '-h') OR
	   (ParamStr(1) = '-H')
	 ) THEN BEGIN
    WriteLn ('Syntax: >SLDDXB [?] [Slide File[.SLD]] [DXB File[.DXB]]');
    WriteLn;
    WriteLn ('Konvertiert ein AutoCAD Dia in eine AutoCAD DXB Datei.');
    WriteLn ('Erkennt automatisch Dias „lterer (vor 9.0) und neuerer Versionen (ab 9.0).');
    WriteLn ('Wird der Name der DXB nicht angegeben, wird der Name der Dia Datei');
    WriteLn ('mit der Extension .SLD angenommen.');
    WriteLn;
    WriteLn ('Beispiel: ');
    WriteLn ('  >SLDDXB DIA1');
    WriteLn ('konvertiert DIA1.SLD in DIA1.DXB');
    Halt (1);
    END;

    CASE ParamCount OF
      0: BEGIN
	 Write ('Diadatei: ');
	 ReadLn (SldName);
	 Write ('DXB Datei: ');
	 ReadLn (DXBName);
	 END;
      1: BEGIN
	 SldName := ParamStr(1);
	 DXBName := '';
	 END;
      2..10: BEGIN
	 SldName := ParamStr(1);
	 DXBName := ParamStr(2);
	 END;
      ELSE Error ('ungltige Parameter Anzahl!');
      END;

    FSplit (SldName, dir, n1, ext);
    IF ext = '' THEN ext := '.SLD';
    SldName := dir + n1 + ext;

    FSplit (DXBName, dir, n2, ext);
    IF n2 = '' THEN n2 := n1;
    IF ext = '' THEN ext := '.DXB';
    DXBName := dir + n2 + ext;

    {$I-}
    Assign (SldFile, SldName);
    Reset (SldFile, 1);
    {$I+}
    IF IOResult <> 0 THEN Error ('Diadatei nicht gefunden!');

    {$I-}
    Assign (DXBFile, DXBName);
    Rewrite (DXBFile, 1);
    {$I+}
    IF IOResult <> 0 THEN Error ('Fehler beim ™ffnen der DXB Datei!');
  END;

PROCEDURE ReadSLDHeader;
  CONST
    id : ARRAY [1..17] of char
    = ('A','u','t','o','C','A','D',' ','S','l','i','d','e',#13,#10,#26,#0);
  VAR
    buf : ARRAY  [1..31] of byte;
    buf1 : ARRAY [1..34] of byte;
    OldHeader : RECORD
      ID_Zeichenkette	  : ARRAY [1..17] of char;
      Typindikator	  : byte;
      Stufenindikator	  : byte;
      High_X_Dot,
      High_Y_Dot	  : integer;
      Aspektverhaeltnis   : double;
      Hardwarefill	  : integer;
      Fuellerbyte	  : byte;
      END ABSOLUTE buf1;

    { neues Format }
    Header : RECORD
      ID_Zeichenkette	  : ARRAY [1..17] of char;
      Typindikator	  : byte;
      Stufenindikator	  : byte;
      High_X_Dot,
      High_Y_Dot	  : integer;
      Aspektverhaeltnis   : longint;
      Hardwarefill	  : integer;
      Testnummer	  : integer;
      END ABSOLUTE buf;
    rr : word;
    maxx, maxy : integer;
    a : double;

  BEGIN  { ReadSLDHeader }
  BlockRead (SldFile, buf, 31, rr);
  IF rr <> 31 THEN
    Error ('Dia Datei zu klein!');
  IF Header.ID_Zeichenkette <> id THEN
    Error ('kein AutoCAD Dia!');
  IF Header.Typindikator <> 86 THEN
    WriteLn ('falscher Typindikator: ',Header.Typindikator,' in Dia Datei!');
  maxx := Header.High_X_Dot;
  maxy := Header.High_Y_Dot;
  IF Header.Stufenindikator <> 2 THEN
    IF Header.Stufenindikator <> 1 THEN
      Error ('falsche Dia Datei Version!')
    ELSE BEGIN
      bSwap := false;
      Reset (SldFile, 1);
      BlockRead (SldFile, buf1, 34, rr);
      IF rr <> 34 THEN
	Error ('Dia Datei zu klein!');
      a := OldHeader.Aspektverhaeltnis;
      END
  ELSE
    BEGIN
    a := Header.Aspektverhaeltnis / 10000000.0;
    bSwap := $1234 <> Header.Testnummer;
    END;
  ax := 1 / max (maxx,maxy);
  ay := 1 / max (maxx,maxy);
  END;	{ ReadSLDHeader }

PROCEDURE DXBNumberMode;
{ alle folgenden dxb_n_Typen bezeichnen double Werte }
  VAR
    b : byte;
    w : dxb_w_type;
  BEGIN
  b := 135;	BlockWrite (DXBFile, b, 1);
  w := 1;	BlockWrite (DXBFile, w, 2);
  END;


PROCEDURE DXBNewColor (col : byte);
  VAR
    b : byte;
    w : dxb_w_type;
  BEGIN
  b := 136;	BlockWrite (DXBFile, b, 1);
  w := col;	BlockWrite (DXBFile, w, 2);
  END;

PROCEDURE DXBLine (x1, y1, x2, y2 : integer);
  VAR
    b : byte;
    n : dxb_n_type;
  BEGIN
  b := 1;	BlockWrite (DXBFile, b, 1);
  n := x1*ax; BlockWrite (DXBFile, n, nl);
  n := y1*ay; BlockWrite (DXBFile, n, nl);
  n := x2*ax; BlockWrite (DXBFile, n, nl);
  n := y2*ay; BlockWrite (DXBFile, n, nl);
  END;

PROCEDURE DXBSolid (x1, y1, x2, y2, x3, y3, x4, y4 : integer);
  VAR
    b : byte;
    n : dxb_n_type;
  BEGIN
  b := 11;	BlockWrite (DXBFile, b, 1);
  n := x1*ax; BlockWrite (DXBFile, n, nl);
  n := y1*ay; BlockWrite (DXBFile, n, nl);
  n := x2*ax; BlockWrite (DXBFile, n, nl);
  n := y2*ay; BlockWrite (DXBFile, n, nl);
  n := x3*ax; BlockWrite (DXBFile, n, nl);
  n := y3*ay; BlockWrite (DXBFile, n, nl);
  n := x4*ax; BlockWrite (DXBFile, n, nl);
  n := y4*ay; BlockWrite (DXBFile, n, nl);
  END;

PROCEDURE DXBCloseUp;
  VAR
    b : byte;
  BEGIN
  b := 0;	BlockWrite (DXBFile, b, 1);
  END;

FUNCTION geti : integer;
  VAR
    i : integer;
  BEGIN
  BlockRead (SLDFile, i, 2);
  IF bSwap THEN i := Swap (i);
  geti := i;
  END;

FUNCTION getb : byte;
  VAR
    b : byte;
  BEGIN
  BlockRead (SLDFile, b, 1);
  getb := b;
  END;

FUNCTION sigbyte (b : byte): integer;
  BEGIN
  IF b < 128
    THEN sigbyte := b
    ELSE sigbyte := b - 256;
  END;

PROCEDURE Convert;
  CONST
    DXB_Header : ARRAY [1..19] of char
      = ('A','u','t','o','C','A','D',' ','D','X','B',' ','1','.','0', #13,#10,#26,#0);
  VAR
    first : integer;
    x1, y1, x2, y2 : integer;
    aktx, akty : integer;	     { letzter Punkt von SLD Vektor }

  BEGIN  { Convert }
  BlockWrite (DXBFile, DXB_Header, sizeof(DXB_Header));
  DXBNumberMode;
  WHILE NOT Eof(SLDFile) DO
    BEGIN
    first := geti;
    CASE Hi(first) OF
      0..$7F:		{ Vektor }
        BEGIN
        aktx := first; akty := geti;
        DXBLine (aktx, akty, geti, geti);
        END;
      $FE:		{ gemeinsamer Endpunktvektor }
        BEGIN
        x1 := aktx + sigbyte (Lo (first));
        y1 := akty + sigbyte (getb);
        DXBLine (aktx, akty, x1, y1);
        aktx := x1; akty := y1;
        END;
      $FB:		{ Versetzungsvektor }
        BEGIN
        x1 := aktx + sigbyte (Lo (first));
        y1 := akty + sigbyte (getb);
        x2 := aktx + sigbyte (getb);
        y2 := akty + sigbyte (getb);
        DXBLine (x1, y1, x2, y2);
        aktx := x1; akty := y1;
        END;
      $FD:		{ Solid fllen }
        BEGIN
        first:= geti;	{ Solid wird nicht konvertiert }
        first:= geti;
        END;
      $FF:		{ neue Farbe }
        DXBNewColor (Lo(first));
      $FC:		{ Dateiende }
        IF Lo(first)=0 THEN Exit
        ELSE Error ('falsche Dateiende Marke in Dia Datei!');
      $80..$FA:		{ Undefiniert }
        BEGIN
        END;
      END;
    END;
  END;	{ Convert }

PROCEDURE Finish;
  BEGIN
  DXBCloseUp;
  Close (SLDFile);
  Close (DXBFile);
  END;

BEGIN
Init;
ReadSLDHeader;
Convert;
Finish;
END.

