Author Topic: Linetype is purged  (Read 10339 times)

0 Members and 1 Guest are viewing this topic.

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4076
Linetype is purged
« on: April 10, 2008, 03:19:44 PM »
Building on Kerry's great example of Layer code, I am trying to incorporate linetypes.
Code: [Select]
layerId = lt[layerName];
if (layerId.IsErased)
{
LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(layerId, OpenMode.ForWrite, true);
ltr.Erase(false);
}


Code: [Select]
if (ltypeId.IsErased)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
   LinetypeTableRecord lttr = (LinetypeTableRecord)tr.GetObject(ltypeId, OpenMode.ForWrite, true);
   lttr.Erase(false);
   tr.Commit();
}
}
The obvious difference is I had to start a transaction, but it still crashes on lttr.erase false
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

Glenn R

  • Guest
Re: Linetype is purged
« Reply #1 on: April 10, 2008, 03:22:48 PM »
Complex linetype?

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Linetype is purged
« Reply #2 on: April 10, 2008, 03:47:59 PM »
Complex linetype?

you mean the linetype has a dependency that no longer exists ??


David ,
Interesting problem ; does it happen consistantly ?

must run ,, a train to catch !
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4076
Re: Linetype is purged
« Reply #3 on: April 10, 2008, 03:50:35 PM »
no, just Hidden.  the problem was I had done a purge , and when I reloaded lilnetypes, it spits the dummy
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4076
Re: Linetype is purged
« Reply #4 on: April 10, 2008, 03:52:50 PM »
I am posting all of the code, mine at the top, Kerry's example commented out at the bottem.

Code: [Select]
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Colors;
using Autodesk.AutoCAD.EditorInput;
using System.Diagnostics;

namespace LayerCode
{
    public class LayerCode
    {

        [CommandMethod("CD3")]
        static public void createduhlayer()
        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead, false) as LayerTable;
                if (lt == null)
                    return;
                if (lt.Has("DSH"))
                    return;
                LayerTableRecord newLTR = new LayerTableRecord();
                newLTR.Name = "DSH";
                newLTR.Color = Color.FromColorIndex(ColorMethod.ByAci, 2);
                // set any other properties

                lt.UpgradeOpen();
                lt.Add(newLTR);

                tr.AddNewlyCreatedDBObject(newLTR, true);

                tr.Commit();
            }
            createLayer("Duh2");
            createLayer("Duh3", 5, "Hidden");
            //createLayerXML("Duh3");
        }

        static public void createLayer(string Lname) //passing a Layername to function
        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead, false) as LayerTable;
                if (lt == null)
                    return;
                if (lt.Has(Lname))
                    return;
                LayerTableRecord newLTR = new LayerTableRecord();
                newLTR.Name = Lname;
                newLTR.Color = Color.FromColorIndex(ColorMethod.ByAci, 2);
                // set any other properties

                lt.UpgradeOpen();
                lt.Add(newLTR);

                tr.AddNewlyCreatedDBObject(newLTR, true);

                tr.Commit();

            }
        }

        static public void createLayer(string Lname, short ColorNum) //passing a Layername & color to function
        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead, false) as LayerTable;
                if (lt == null)
                    return;
                if (lt.Has(Lname))
                    return;
                LayerTableRecord newLTR = new LayerTableRecord();
                newLTR.Name = Lname;
                newLTR.Color = Color.FromColorIndex(ColorMethod.ByAci, ColorNum);
                // set any other properties

                lt.UpgradeOpen();
                lt.Add(newLTR);

                tr.AddNewlyCreatedDBObject(newLTR, true);

                tr.Commit();

            }
        }
        static public void createLayer(string Lname, short ColorNum, string LType) //passing a Layername,color,ltype to function
        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead, false) as LayerTable;
                if (lt == null)
                    return;
                if (lt.Has(Lname))
                    return;
                LayerTableRecord newLTR = new LayerTableRecord();
                newLTR.Name = Lname;
                newLTR.Color = Color.FromColorIndex(ColorMethod.ByAci, ColorNum);
                newLTR.LinetypeObjectId = GetOrLoadLinetypeId(LType, db);

                lt.UpgradeOpen();
                lt.Add(newLTR);

                tr.AddNewlyCreatedDBObject(newLTR, true);

                tr.Commit();

            }
        }
        public static ObjectId GetOrLoadLinetypeId(string linetypeName, Database db)
        {
            ObjectId ltypeId = GetSymbolTableRecId(typeof(LinetypeTableRecord), linetypeName, db);
            if (ltypeId.IsNull)
            {
                string[] ltypeFiles;
                ltypeFiles = new string[3];
                if (db.Measurement == MeasurementValue.English)
                //if (db.Measurement == MeasurementValue.Metric)
                {
                    PrintToCmdLine(" \n Using English Linetypes");
                    ltypeFiles[0] = "acad.lin";
                    ltypeFiles[1] = "acadiso.lin";
                    ltypeFiles[2] = "ltypeshp.lin";
                }
                else
                {
                    PrintToCmdLine(" \n Using Metric Linetypes");
                    ltypeFiles[0] = "acadiso.lin";
                    ltypeFiles[1] = "acad.lin";
                    ltypeFiles[2] = "ltypeshp.lin";
                }
                //---------------
                int len = ltypeFiles.Length;
                for (int i = 0; i < len; i++)
                {
                    try
                    {
                        // try to load the linetype from the external file
                        db.LoadLineTypeFile(linetypeName, ltypeFiles[i]);

                        ltypeId = GetSymbolTableRecId(typeof(LinetypeTableRecord), linetypeName, db);
                        if (ltypeId.IsErased)
                        {
                            using (Transaction tr = db.TransactionManager.StartTransaction())
                            {
                                LinetypeTableRecord lttr = (LinetypeTableRecord)tr.GetObject(ltypeId, OpenMode.ForWrite, true);
                                lttr.Erase (false  );
                                tr.Commit();
                            }
                        }
                        if (ltypeId.IsNull == false)
                            return ltypeId;
                    }
                    catch (Autodesk.AutoCAD.Runtime.Exception acEx)
                    {
                        if (acEx.Message == "eUndefinedLineType")
                        {
                            PrintToCmdLine(string.Format(
                                    "\n ERROR: Could not load linetype \"{0}\", using CONTINUOUS instead.",
                                    linetypeName));
                            ltypeId = db.ContinuousLinetype;
                            return ltypeId;
                        }
                        else
                        {
                            PrintToCmdLine(string.Format(
                                "\n ERROR: in 'LibTools.GetOrLoadLinetypeId' loading linetype \"{0}\".",
                                linetypeName));
                            throw acEx;
                        }
                    }
                }
            }
            return ltypeId;
        }
        public static ObjectId GetSymbolTableRecId(System.Type classType, string symName, Database db)
        {
            ObjectId tblId = GetSymbolTableId(classType, db);
            ObjectId recId = new ObjectId();

            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                SymbolTable tbl = (SymbolTable)tr.GetObject(tblId, OpenMode.ForRead);
                if (tbl.Has(symName))   // TBD: should indexer return ObjectId.null instead of throwing exception
                    recId = tbl[symName];
                tr.Commit();
            }
            return recId;
        }
        public static ObjectId GetSymbolTableId(System.Type classType, Database db)
        {
            Debug.Assert(classType != null);
            Debug.Assert(db != null);

            if (classType == typeof(BlockTableRecord))
                return db.BlockTableId;
            else if (classType == typeof(DimStyleTableRecord))
                return db.DimStyleTableId;
            else if (classType == typeof(LayerTableRecord))
                return db.LayerTableId;
            else if (classType == typeof(LinetypeTableRecord))
                return db.LinetypeTableId;
            else if (classType == typeof(TextStyleTableRecord))
                return db.TextStyleTableId;
            else if (classType == typeof(RegAppTableRecord))
                return db.RegAppTableId;
            else if (classType == typeof(UcsTableRecord))
                return db.UcsTableId;
            else if (classType == typeof(ViewTableRecord))
                return db.ViewTableId;
            else if (classType == typeof(ViewportTableRecord))
                return db.ViewportTableId;
            else
            {
                Debug.Assert(false);
                ObjectId nullObj = new ObjectId();
                return nullObj;
            }
        }
        static public void createLayerXML(string Lname)
        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {

                LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead, false) as LayerTable;
                if (lt == null)
                    return;
                if (lt.Has(Lname))
                {
                    return;
                }
                else
                {
                    DataSet dsLayerData = new DataSet();
                    dsLayerData.ReadXml(@"c:\LayerDefinitions.xml");
                    DataView dsLayerDefinition = new DataView(dsLayerData.Tables["Layer"]);
                    dsLayerDefinition.Sort = "LayerName";

                    int rowIndex = dsLayerDefinition.Find(Lname);
                    if (rowIndex == -1)
                    {
                        ed.WriteMessage("Bogus Layer Name");
                    }
                    else
                    {
                        short lC = Convert.ToInt16(dsLayerDefinition[rowIndex]["Color"]);
                        string lnT = dsLayerDefinition[rowIndex]["LineType"].ToString();
                        LinetypeTable LTT = tr.GetObject(db.LinetypeTableId, OpenMode.ForRead, false) as LinetypeTable;
                        if (LTT == null)
                            return;
                        if (LTT.Has(lnT))
                            return;
                        else
                        {
                            LinetypeTableRecord newLTTR = new LinetypeTableRecord();
                            newLTTR.Name = lnT;
                            LTT.UpgradeOpen();
                            LTT.Add(newLTTR);
                            tr.AddNewlyCreatedDBObject(newLTTR, true);
                        }
                        //string layerColor = dsLayerDefinition[rowIndex]["Color"].ToString();
                        //short  lC = Convert.ToInt16(layerColor);
                        LayerTableRecord newLTR = new LayerTableRecord();
                        newLTR.Name = Lname;
                        newLTR.Color = Color.FromColorIndex(ColorMethod.ByAci, lC);
                        //newLTR.LinetypeObjectId = newLTTR;
                        lt.UpgradeOpen();
                        lt.Add(newLTR);
                        tr.AddNewlyCreatedDBObject(newLTR, true);
                    }
                }

                // set any other properties
                tr.Commit();
            }
        }
        public static void PrintToCmdLine(string str)
        {
            Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
            ed.WriteMessage(str);
        }
    }
}
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4076
Re: Linetype is purged
« Reply #5 on: April 10, 2008, 03:53:34 PM »
Code: [Select]
/*#region System using declarations
using System;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;

using System.Text;
//using System.Drawing;
using System.Reflection;
//using System.Windows.Forms;
using System.ComponentModel;
using System.Text.RegularExpressions;
#endregion

#region AutoCAD COM Interop using declarations
//// COM Interop References
//// AutoCAD 2006 Type Library
//using Autodesk.AutoCAD.Interop;

//// AXDBLib AutoCAD/ObjectDBX Common 16.0 Type Library
//using Autodesk.AutoCAD.Interop.Common;

#endregion

#region AutoCAD Managed Wrappers using declarations
//// Assembly acdbmgd .. ObjectDBX.NET Managed Wrapper
//// Assembly acmgd .. Autocad.NET Managed Wrapper
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Colors;
#endregion

#region Alias using declarations
using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;
#endregion

[assembly: ExtensionApplication(typeof(ClassLibraryLab03.kwbLab03StartApp))]
[assembly: CommandClass(typeof(ClassLibraryLab03.Commands))]

namespace ClassLibraryLab03
{
    #region CommandClass
    //-------------------------------------------------------------------------------
    public class
    Commands
    {
        [CommandMethod("Lab03Help", CommandFlags.Modal)]
        static public void
        Lab03Help()
        {
            Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;

            ed.WriteMessage("\n  Testing Assembly kwbLab03 [kwb v:20051204]");
            ed.WriteMessage("\n  Commands : LX1, LX2, LX3, LX4, LX5");
        }

        //----------------------------
        [CommandMethod("LX1", CommandFlags.Modal)]
        public static void AssertLayerLX1()
        {
            Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;
            try
            {
                ObjectId layerId = LibTools.CreateLayer("TestX1", 3, "HIDDEN");
                ed.WriteMessage("\n  layerId : " + layerId.ToString());
            }
            catch (Autodesk.AutoCAD.Runtime.Exception acEx)
            {
                ed.WriteMessage("\nError: " + acEx.Message);
                return;
            }
        }
        //----------------------------
        [CommandMethod("LX2", CommandFlags.Modal)]
        public static void AssertLayerLX2()
        {
            Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;
            try
            {
                ObjectId layerId = LibTools.CreateLayer(" ", 113, "CONTINUOUS");
                ed.WriteMessage("\n  layerId : " + layerId.ToString());
            }
            catch (Autodesk.AutoCAD.Runtime.Exception acEx)
            {
                ed.WriteMessage("\nError: " + acEx.Message);
                return;
            }
        }
        //----------------------------
        [CommandMethod("LX3", CommandFlags.Modal)]
        public static void AssertLayerLX3()
        {
            Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;
            try
            {
                ObjectId layerId = LibTools.CreateLayer("TestX3", 13, "NONE");
                ed.WriteMessage("\n  layerId : " + layerId.ToString());
            }
            catch (Autodesk.AutoCAD.Runtime.Exception acEx)
            {
                ed.WriteMessage("\nError: " + acEx.Message);
                return;
            }
        }
        //----------------------------
        [CommandMethod("LX4", CommandFlags.Modal)]
        public static void AssertLayerLX4()
        {
            Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;
            try
            {
                ObjectId layerId = LibTools.CreateLayer("Test X4", 230, "DOT");
                ed.WriteMessage("\n  layerId : " + layerId.ToString());
            }
            catch (Autodesk.AutoCAD.Runtime.Exception acEx)
            {
                ed.WriteMessage("\nError: " + acEx.Message);
                return;
            }
        }
        //----------------------------
        [CommandMethod("LX5", CommandFlags.Modal)]
        public static void AssertLayerLX5()
        {
            Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;
            try
            {
                ObjectId layerId = LibTools.CreateLayer("TestX5", 30000, "");
                ed.WriteMessage("\n  layerId : " + layerId.ToString());
            }
            catch (Autodesk.AutoCAD.Runtime.Exception acEx)
            {
                ed.WriteMessage("\nError: " + acEx.Message);
                return;
            }
        }
        //----------------------------
    }
    #endregion



    #region MainApp core
    //-------------------------------------------------------------------------------
    //public class Class1
    //{
    //}
    #endregion


    #region LibraryTools
    //-------------------------------------------------------------------------------
    public class LibTools
    {
        //----------------------------
        public static ObjectId CreateLayer(string layerName, short layerColor, string linetypeName)
        {
            ObjectId layerId;
            Database  db = HostApplicationServices.WorkingDatabase;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForWrite);

                if (lt.Has(layerName))
                {
                    layerId = lt[layerName];
                    if (layerId.IsErased)
                    {
                        LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(layerId, OpenMode.ForWrite, true);
                        ltr.Erase(false);
                    }
                }
                else // create the layer here.
                {
                    if (layerColor > 255)
                    {
                        LibTools.PrintToCmdLine(string.Format(
                            "\n ERROR: Could not use LayerColor \"{0}\", using O instead.", layerColor));
                        layerColor = 0;
                    }

                    LayerTableRecord ltr = new LayerTableRecord();
                    ltr.Name = layerName;
                    ltr.Color = Autodesk.AutoCAD.Colors.Color.FromColorIndex(ColorMethod.ByAci, layerColor);
                    ltr.LinetypeObjectId = GetOrLoadLinetypeId(linetypeName, db);
                    layerId = lt.Add(ltr);
                    tr.AddNewlyCreatedDBObject(ltr, true);
                }
                tr.Commit();
            }
            return layerId;
        }
        //----------------------------
        public static ObjectId
        GetOrLoadLinetypeId(string linetypeName, Database db)
        {
            ObjectId ltypeId = GetSymbolTableRecId(typeof(LinetypeTableRecord), linetypeName, db);
            if (ltypeId.IsNull)
            {
                string[] ltypeFiles;
                ltypeFiles = new string[3];
                if (db.Measurement == MeasurementValue.Metric)
                {
                    LibTools.PrintToCmdLine(" \n Using Metric Linetypes");
                    ltypeFiles[0] = "acadiso.lin";
                    ltypeFiles[1] = "acad.lin";
                    ltypeFiles[2] = "ltypeshp.lin";
                }
                else
                {
                    LibTools.PrintToCmdLine(" \n Using English Linetypes");
                    ltypeFiles[0] = "acad.lin";
                    ltypeFiles[1] = "acadiso.lin";
                    ltypeFiles[2] = "ltypeshp.lin";
                }
                //---------------
                int len = ltypeFiles.Length;
                for (int i = 0; i < len; i++)
                {
                    try
                    {
                        // try to load the linetype from the external file
                        db.LoadLineTypeFile(linetypeName, ltypeFiles[i]);

                        ltypeId = GetSymbolTableRecId(typeof(LinetypeTableRecord), linetypeName, db);
                        if (ltypeId.IsNull == false)
                            return ltypeId;
                    }
                    catch (Autodesk.AutoCAD.Runtime.Exception acEx)
                    {
                        if (acEx.Message == "eUndefinedLineType")
                        {
                            LibTools.PrintToCmdLine(string.Format(
                                    "\n ERROR: Could not load linetype \"{0}\", using CONTINUOUS instead.",
                                    linetypeName));
                            ltypeId = db.ContinuousLinetype;
                            return ltypeId;
                        }
                        else
                        {
                            LibTools.PrintToCmdLine(string.Format(
                                "\n ERROR: in 'LibTools.GetOrLoadLinetypeId' loading linetype \"{0}\".",
                                linetypeName));
                            throw acEx;
                        }
                    }
                }
            }
            return ltypeId;
        }
        //---------------------------- awej MgdDbg rev.
        public static ObjectId
        GetSymbolTableRecId(System.Type classType, string symName, Database db)
        {
            ObjectId tblId = GetSymbolTableId(classType, db);
            ObjectId recId = new ObjectId();

            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                SymbolTable tbl = (SymbolTable)tr.GetObject(tblId, OpenMode.ForRead);
                if (tbl.Has(symName))   // TBD: should indexer return ObjectId.null instead of throwing exception
                    recId = tbl[symName];
                tr.Commit();
            }
            return recId;
        }
        //---------------------------- awej MgdDbg rev.
        public static ObjectId
         GetSymbolTableId(System.Type classType, Database db)
        {
            Debug.Assert(classType != null);
            Debug.Assert(db != null);

            if (classType == typeof(BlockTableRecord))
                return db.BlockTableId;
            else if (classType == typeof(DimStyleTableRecord))
                return db.DimStyleTableId;
            else if (classType == typeof(LayerTableRecord))
                return db.LayerTableId;
            else if (classType == typeof(LinetypeTableRecord))
                return db.LinetypeTableId;
            else if (classType == typeof(TextStyleTableRecord))
                return db.TextStyleTableId;
            else if (classType == typeof(RegAppTableRecord))
                return db.RegAppTableId;
            else if (classType == typeof(UcsTableRecord))
                return db.UcsTableId;
            else if (classType == typeof(ViewTableRecord))
                return db.ViewTableId;
            else if (classType == typeof(ViewportTableRecord))
                return db.ViewportTableId;
            else
            {
                Debug.Assert(false);
                ObjectId nullObj = new ObjectId();
                return nullObj;
            }
        }
        //----------------------------
        public static void
        PrintToCmdLine(string str)
        {
            Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;
            ed.WriteMessage(str);
        }
        //----------------------------
    }
    #endregion


    #region Public class StartApp
    //-------------------------------------------------------------------------------
    /// <summary>
    /// The entry point for AutoCAD.
    /// </summary>
    public class
    kwbLab03StartApp : IExtensionApplication
    {
        public void
        Initialize()
        {
            Editor  ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;

            Commands.Lab03Help();
            ed.WriteMessage("\n  Type 'Lab03Help' at the Command Line for assistance ...");
        }
        public void
        Terminate()
        {
            // Does Nothing ... can't unload NET assembly ...
        }
    }
    #endregion
}
*/
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4076
Re: Linetype is purged
« Reply #6 on: April 10, 2008, 03:55:17 PM »
David ,
Interesting problem ; does it happen consistantly ?
Yes, well at least every time I try to crash it I can.  To reproduce problem, load a linetype (I used Hidden) and assign to a unused layer.  Then purge dwg.  Then call the function which loads the linetypes
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

Glenn R

  • Guest
Re: Linetype is purged
« Reply #7 on: April 10, 2008, 04:00:00 PM »
Complex linetype?

you mean the linetype has a dependency that no longer exists ??


Yep.

Duh,

This is the problem I ran into in 2005 and apparently it still exists...the default indexer problem.

Linkage

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4076
Re: Linetype is purged
« Reply #8 on: April 10, 2008, 04:01:16 PM »
I guess I forgot to mention that it appears to work UNTIL you open the Layer manager, at which point you get these screen shots.
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4076
Re: Linetype is purged
« Reply #9 on: April 10, 2008, 04:02:24 PM »
And Kerry, the above screen shots were created using your LX1  from the LibTools code you gave me
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

Glenn R

  • Guest
Re: Linetype is purged
« Reply #10 on: April 10, 2008, 04:08:57 PM »
Here is TonyT's solution which is the best I've seen for this problem and is the one I use:

Linkage

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4076
Re: Linetype is purged
« Reply #11 on: April 10, 2008, 04:23:52 PM »
thanks Glenn, I need to read what he did and see how to use it
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4076
Re: Linetype is purged
« Reply #12 on: April 10, 2008, 04:44:25 PM »
Glenn, I must confess I don't quite understand how to use TT's code.
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4076
Re: Linetype is purged
« Reply #13 on: April 11, 2008, 05:49:08 PM »
Well I have tried all sorts of things today, and cant seem to figure out what I am missing.  Maybe I'll try to fix it this weekend
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Linetype is purged
« Reply #14 on: April 11, 2008, 05:52:40 PM »
David,

'cause today is my playday I'll have a look too if I clear my todo list.

can you post or send the XML definition file, just for completeness.

Be well
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4076
Re: Linetype is purged
« Reply #15 on: April 11, 2008, 05:58:05 PM »
Kerry, I was actually not using your XML file, is that the problem?  I was just passing the Linetype name I wanted manually thru code
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

Glenn R

  • Guest
Re: Linetype is purged
« Reply #16 on: April 11, 2008, 05:58:44 PM »
can you post or send the XML definition file, just for completeness.

My eyes are hanging out of my head on stalks at the moment and I might have missed something, but...what XML file?

Duh,

What have you tried exactly? What stumped you about Tony's implementation?

Cheers,
Glenn.

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4076
Re: Linetype is purged
« Reply #17 on: April 11, 2008, 06:04:32 PM »
Glenn, Kerry's code has a part where he reads an XML file and creates layers based on the file.  I can post it if you need it.

The part that is stumping me is I am not sure what Im supposed to pass to his code to grab the "erased" id.  I'm also assuming you used the second piece(s) of code as that was being touted as faster/better.
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Linetype is purged
« Reply #18 on: April 11, 2008, 06:05:27 PM »
can you post or send the XML definition file, just for completeness.

My eyes are hanging out of my head on stalks at the moment and I might have missed something, but...what XML file?

< ... >
Cheers,
Glenn.

        static public void createLayerXML(string Lname)
        {
  //*

...
*//
                {
                    DataSet dsLayerData = new DataSet();
                    dsLayerData.ReadXml(@"c:\LayerDefinitions.xml");
                    DataView dsLayerDefinition = new DataView(dsLayerData.Tables["Layer"]);
                    dsLayerDefinition.Sort = "LayerName";
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4076
Re: Linetype is purged
« Reply #19 on: April 11, 2008, 06:16:24 PM »
I copied this into my code
Code: [Select]
//      // This is a much better/faster solution that P/Invokes
//      // AcDbSymbolTableRecord::getAt() directly from managed code:


        public static class AcDbSymbolTable
        {
            // Acad::ErrorStatus AcDbSymbolTable::getAt(wchar_t const *, class AcDbObjectId &, bool)

            [System.Security.SuppressUnmanagedCodeSecurity]
            [DllImport("acdb17.dll", CallingConvention = CallingConvention.ThisCall, CharSet = CharSet.Unicode,
               EntryPoint = "?getAt@AcDbSymbolTable@@QBE?AW4ErrorStatus@Acad@@PB_WAAVAcDbObjectId@@_N@Z")]

            public static extern ErrorStatus getAt(IntPtr symbolTable, string name, out ObjectId id, bool getErased);
        }

        public static ObjectId GetSymbolTableRecordId(SymbolTable table, string name)
        {
            ObjectId id = ObjectId.Null;
            ErrorStatus es = AcDbSymbolTable.getAt(table.UnmanagedObject, name, out id, false);
            return id;
        }

        public static ObjectId GetSymbolTableRecordId(ObjectId TableId, string name)
        {
            using (Transaction tr = TableId.Database.TransactionManager.StartTransaction())
            {
                SymbolTable table = (SymbolTable)tr.GetObject(TableId, OpenMode.ForRead);
                try
                {
                    return GetSymbolTableRecordId(table, name);
                }
                finally
                {
                    tr.Commit();
                }
            }
        }
and then was trying to figure out what to pass to which function to get the ID of the erased Linetype, and then trying to figure out how to unerase it.
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

Glenn R

  • Guest
Re: Linetype is purged
« Reply #20 on: April 11, 2008, 06:17:03 PM »
Very quick and off the top of my head from looking at Tony's code again:

Code: [Select]
Database db = ...;

ObjectId someLinetypeTableRecordId = ObjectId.Null;

someLinetypeTableRecordId = DBUtils.GetSymbolTableRecordId(db.LinetypeTableRecord, "SomeLineTypeNameGoesHere");

if (someLinetypeTableRecordId != ObjectId.Null)
  // do some funky mojo here...


Glenn R

  • Guest
Re: Linetype is purged
« Reply #21 on: April 11, 2008, 06:18:26 PM »
You REALLY don't want to UNERASE it. Read the discussion I posted earlier from the Adesk NG where Tony and I were discussing this particular problem.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Linetype is purged
« Reply #22 on: April 11, 2008, 06:21:20 PM »
FYI....

If you want to test if an ObjectId is Null, you can just use the property 'IsNull'.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4076
Re: Linetype is purged
« Reply #23 on: April 14, 2008, 10:52:52 AM »
I must need more coffee, b/c I just re read the discussion b/t you and TT, and I just dont get it.  What I think I am supposed to do is check for the name and if its erased, create a new one.
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Linetype is purged
« Reply #24 on: April 14, 2008, 11:19:04 AM »
I must need more coffee, b/c I just re read the discussion b/t you and TT, and I just dont get it.  What I think I am supposed to do is check for the name and if its erased, create a new one.
That is how I do it in an insert block routine I just did, so I hope it is the right approach.  Mine works without crashing, so I figured it was a good solution.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4076
Re: Linetype is purged
« Reply #25 on: April 14, 2008, 11:20:09 AM »
Thanks Tim.  I'll try and post what I got if I get to it today.
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

Glenn R

  • Guest
Re: Linetype is purged
« Reply #26 on: April 14, 2008, 11:49:36 AM »
I must need more coffee, b/c I just re read the discussion b/t you and TT, and I just dont get it.  What I think I am supposed to do is check for the name and if its erased, create a new one.

Essentially, yes.

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4076
Re: Linetype is purged
« Reply #27 on: April 14, 2008, 04:32:49 PM »
Thanks Glenn!  Only being able to look at this stuff every couple of weeks makes it very difficult to keep rational thoughts about what I was/am doing, and where I need to go.
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4076
Re: Linetype is purged
« Reply #28 on: May 27, 2008, 02:31:04 PM »
wow, looking at my last post, and then checking the date, its been a while.  Oh well, I have 2 days to work on this, and then I'm gone for a week.
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4076
Re: Linetype is purged
« Reply #29 on: May 27, 2008, 02:53:01 PM »
Well, I have some very good news!!!!!  It looks like they fixed the problem in 2009  :lol: :lol: :lol:  I loaded 09 last week, and just for grins decided to tell VS2008 to use 09.  Not remembering where I was with the whole problem, I began stepping thru the code to repeat the problem, and it ran flawlessly.  More testing to follow, but I think it is golden with regard to erased records
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

Glenn R

  • Guest
Re: Linetype is purged
« Reply #30 on: May 28, 2008, 04:53:04 AM »
Hmmm...can you confirm that Duh? I was under the impression (from an adesk newsgroup post) that this flaw still remained in 2009..............

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4076
Re: Linetype is purged
« Reply #31 on: May 28, 2008, 09:43:10 AM »
Code: [Select]
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Colors;
using Autodesk.AutoCAD.EditorInput;
using System.Diagnostics;
using System.Runtime.InteropServices;


namespace LayerCode
{
    public class LayerCode
    {

        [CommandMethod("DDD")]
        static public void createduhlayer()
        {
            //Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            //Database db = doc.Database;
            //Editor ed = doc.Editor;
            //using (Transaction tr = db.TransactionManager.StartTransaction())
            //{
                //LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead, false) as LayerTable;
                //if (lt == null)
                //    return;
                //if (lt.Has("DSH"))
                //    return;
                //LayerTableRecord newLTR = new LayerTableRecord();
                //newLTR.Name = "DSH";
                //newLTR.Color = Color.FromColorIndex(ColorMethod.ByAci, 2);
                //// set any other properties

                //lt.UpgradeOpen();
                //lt.Add(newLTR);

                //tr.AddNewlyCreatedDBObject(newLTR, true);

                //tr.Commit();

                createLayer("Duh2");
                createLayer("DSH", 2);
                createLayerXML("Duh3");
            //}
            //createLayerXML("Duh3");
        }

        static public void createLayer(string Lname)
        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead, false) as LayerTable;
                if (lt == null)
                    return;
                if (lt.Has(Lname))
                    return;
                LayerTableRecord newLTR = new LayerTableRecord();
                newLTR.Name = Lname;
                newLTR.Color = Color.FromColorIndex(ColorMethod.ByAci, 2);
                // set any other properties

                lt.UpgradeOpen();
                lt.Add(newLTR);

                tr.AddNewlyCreatedDBObject(newLTR, true);

                tr.Commit();

            }
        }

        static public void createLayer(string Lname, short ColorNum)
        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead, false) as LayerTable;
                if (lt == null)
                    return;
                if (lt.Has(Lname))
                    return;
                LayerTableRecord newLTR = new LayerTableRecord();
                newLTR.Name = Lname;
                newLTR.Color = Color.FromColorIndex(ColorMethod.ByAci, ColorNum);
                // set any other properties

                lt.UpgradeOpen();
                lt.Add(newLTR);

                tr.AddNewlyCreatedDBObject(newLTR, true);

                tr.Commit();

            }
        }
        static public void createLayer(string Lname, short ColorNum, string LType)
        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead, false) as LayerTable;
                if (lt == null)
                    return;
                if (lt.Has(Lname))
                    return;
                LayerTableRecord newLTR = new LayerTableRecord();
                newLTR.Name = Lname;
                newLTR.Color = Color.FromColorIndex(ColorMethod.ByAci, ColorNum);
                newLTR.LinetypeObjectId = GetOrLoadLinetypeId(LType, db);

                lt.UpgradeOpen();
                lt.Add(newLTR);

                tr.AddNewlyCreatedDBObject(newLTR, true);

                tr.Commit();

            }
        }

     
        public static ObjectId GetOrLoadLinetypeId(string linetypeName, Database db)
        {
            ObjectId ltypeId = GetSymbolTableRecId(typeof(LinetypeTableRecord), linetypeName, db);
            if (ltypeId.IsNull)
            {
                string[] ltypeFiles;
                ltypeFiles = new string[3];
                if (db.Measurement == MeasurementValue.English)
                //if (db.Measurement == MeasurementValue.Metric)
                {
                    PrintToCmdLine(" \n Using English Linetypes");
                    ltypeFiles[0] = "acad.lin";
                    ltypeFiles[1] = "acadiso.lin";
                    ltypeFiles[2] = "ltypeshp.lin";
                }
                else
                {
                    PrintToCmdLine(" \n Using Metric Linetypes");
                    ltypeFiles[0] = "acadiso.lin";
                    ltypeFiles[1] = "acad.lin";
                    ltypeFiles[2] = "ltypeshp.lin";
                }
                //---------------
                int len = ltypeFiles.Length;
                for (int i = 0; i < len; i++)
                {
                    try
                    {
                        // try to load the linetype from the external file
                        db.LoadLineTypeFile(linetypeName, ltypeFiles[i]);

                        ltypeId = GetSymbolTableRecId(typeof(LinetypeTableRecord), linetypeName, db);
                        if (ltypeId.IsErased)
                        {
                            using (Transaction tr = db.TransactionManager.StartTransaction())
                            {
                                LinetypeTableRecord lttr = (LinetypeTableRecord)tr.GetObject(ltypeId, OpenMode.ForWrite, true);
                                lttr.Erase(false);
                                tr.Commit();
                            }
                        }
                        if (ltypeId.IsNull == false)
                            return ltypeId;
                    }
                    catch (Autodesk.AutoCAD.Runtime.Exception acEx)
                    {
                        if (acEx.Message == "eUndefinedLineType")
                        {
                            PrintToCmdLine(string.Format(
                                    "\n ERROR: Could not load linetype \"{0}\", using CONTINUOUS instead.",
                                    linetypeName));
                            ltypeId = db.ContinuousLinetype;
                            return ltypeId;
                        }
                        else
                        {
                            PrintToCmdLine(string.Format(
                                "\n ERROR: in 'LibTools.GetOrLoadLinetypeId' loading linetype \"{0}\".",
                                linetypeName));
                            throw acEx;
                        }
                    }
                }
            }
            return ltypeId;
        }
        public static ObjectId GetSymbolTableRecId(System.Type classType, string symName, Database db)
        {
            ObjectId tblId = GetSymbolTableId(classType, db);
            ObjectId recId = new ObjectId();

            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                SymbolTable tbl = (SymbolTable)tr.GetObject(tblId, OpenMode.ForRead,true);
                if (tbl.Has(symName))   // TBD: should indexer return ObjectId.null instead of throwing exception
                    recId = tbl[symName];
                tr.Commit();
            }
            return recId;
        }
        public static ObjectId GetSymbolTableId(System.Type classType, Database db)
        {
            Debug.Assert(classType != null);
            Debug.Assert(db != null);

            if (classType == typeof(BlockTableRecord))
                return db.BlockTableId;
            else if (classType == typeof(DimStyleTableRecord))
                return db.DimStyleTableId;
            else if (classType == typeof(LayerTableRecord))
                return db.LayerTableId;
            else if (classType == typeof(LinetypeTableRecord))
                return db.LinetypeTableId;
            else if (classType == typeof(TextStyleTableRecord))
                return db.TextStyleTableId;
            else if (classType == typeof(RegAppTableRecord))
                return db.RegAppTableId;
            else if (classType == typeof(UcsTableRecord))
                return db.UcsTableId;
            else if (classType == typeof(ViewTableRecord))
                return db.ViewTableId;
            else if (classType == typeof(ViewportTableRecord))
                return db.ViewportTableId;
            else
            {
                Debug.Assert(false);
                ObjectId nullObj = new ObjectId();
                return nullObj;
            }
        }
        static public void createLayerXML(string Lname)
        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {

                LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead, false) as LayerTable;
                if (lt == null)
                    return;
                if (lt.Has(Lname))
                {
                    return;
                }
                else
                {
                    DataSet dsLayerData = new DataSet();
                    dsLayerData.ReadXml(@"c:\LayerDefinitions.xml");
                    DataView dsLayerDefinition = new DataView(dsLayerData.Tables["Layer"]);
                    dsLayerDefinition.Sort = "LayerName";

                    int rowIndex = dsLayerDefinition.Find(Lname);
                    if (rowIndex == -1)
                    {
                        ed.WriteMessage("Bogus Layer Name");
                    }
                    else
                    {
                        short lC = Convert.ToInt16(dsLayerDefinition[rowIndex]["Color"]);
                        string lnT = dsLayerDefinition[rowIndex]["LineType"].ToString();
                        LinetypeTable LTT = tr.GetObject(db.LinetypeTableId, OpenMode.ForRead, false) as LinetypeTable;
                        if (LTT == null)
                            return;
                        if (LTT.Has(lnT))
                            return;
                        else
                        {
                            LinetypeTableRecord newLTTR = new LinetypeTableRecord();
                            newLTTR.Name = lnT;
                            LTT.UpgradeOpen();
                            LTT.Add(newLTTR);
                            tr.AddNewlyCreatedDBObject(newLTTR, true);
                        }
                        //string layerColor = dsLayerDefinition[rowIndex]["Color"].ToString();
                        //short  lC = Convert.ToInt16(layerColor);
                        LayerTableRecord newLTR = new LayerTableRecord();
                        newLTR.Name = Lname;
                        newLTR.Color = Color.FromColorIndex(ColorMethod.ByAci, lC);
                        //newLTR.LinetypeObjectId = newLTTR;
                        lt.UpgradeOpen();
                        lt.Add(newLTR);
                        tr.AddNewlyCreatedDBObject(newLTR, true);
                    }
                }

                // set any other properties
                tr.Commit();
            }
        }
        public static void PrintToCmdLine(string str)
        {
            Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
            ed.WriteMessage(str);
        }
    }
}
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4076
Re: Linetype is purged
« Reply #32 on: May 28, 2008, 09:46:23 AM »
Posted is the code I'm using, most of which came from Kerry (thanks again) and I am trying every way i can think of to load the linetype, purge it out, and rerun the program and make it crash.  I am seeing some strange display behavior in the layer props box, but it runs great.

On a side note, I guess procrastinating for 6 weeks on this problem was a good thing.  I still need to try and understand what TT was doing and make use of it in case there are other broken items I find.
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)