By Lars C. Hassing

LDrawIni is a C API for determining LDrawDir and SearchDirs from settings found in the various combinations of ldraw.ini, LDRAWDIR etc. It is intended to be used by programs supporting the LDraw file format. These programs will then share the same algorithm for determining LDrawDir and SearchDirs, and thus find parts and primitives consistently.

The idea of a common set of routines was conceived in 2004 to allow all LDraw related programs to have an easy way to make sure that the LDraw settings were read correctly, and that parts were searched correctly.

See original LUGNET posting

The basic idea is that it should be very simple to use, there are only four functions and a data structure declaration.

1. First you call LDrawIniGet to determine the LDrawDir and the symbolic search directories. The data is initialized from environment variables and/or ini files suitable for the platform you are running and in the agreed order.

2. Next you call LDrawIniComputeRealDirs to get an array of real directories to look in.

Suppose the user has an ldraw.ini file like this:

   6=<DEFPART>C:\My Own Parts
then calling LDrawIniComputeRealDirs with ModelPath "C:\Users\Lars\AppData\Roaming" will give you this SearchDirs array:
Flags   Dir
LDSDF_MODELDIR   "C:\Users\Lars\AppData\Roaming"
LDSDF_DEFPART   "C:\My Own Parts"
Now you are ready to search for line type 1 references.
If your program needs to load another model, simply repeat step 2 with the new ModelPath.

3. Finally you call LDrawIniFree to free the data structures.

L3P, as an example, will now look for the model in each of the search dirs. When found L3P calls LDrawIniComputeRealDirs with the directory of the model. This will recalculate the search dirs in the data structure to include those with <MODELDIR> . L3P will now (probably) have an extra search dir to look in for the remaining loading of parts. (directories marked with <SKIP> will of course be excluded from the search dirs) For each search dir there may be a number of flags. The known ones are parsed into bit-flags to speed up testing (e.g. LDSDF_HIDE|LDSDF_DEFPRIM), the remaining are available as a string, e.g "<MyFlag><UnknownFlag>". (or would you like a NULL terminated array of strings?) When finding a file in one of the search dirs and the file has no official header L3P can quickly determine whether the default filetype is e.g. Primitive. When done L3P calls LDrawIniFree to release the data structure. L3Lab works the same way, only it calls LDrawIniComputeRealDirs whenever a new model is loaded. The last function is LDrawIniResetSearchDirs, only to be called from the LDrawSetup program - or if you wish to override the search to be the standard one.

For developers

For users

L3P is a command line program, so it has the notion of a current working directory:

struct LDrawIniS *LDrawIni;     /* Info from env var and ldraw.ini files     */

   int            LDrawIniErrorCode;
   int            i;
   FILE          *Fp;

   if (LdconfigLdrRead)

   LDrawIni = LDrawIniGet(MyLDrawDir, 
                          MyLDrawDir ? "-ldd<dir> option" : NULL,
   if (!LDrawIni)
         /* Neither environment variable, nor ldraw.ini, simply try current
            dir                                                              */
         if (L3IsDir("P") && L3IsDir("PARTS") && L3IsDir("MODELS"))
            LDrawIni = LDrawIniGet(".", "Current directory", &LDrawIniErrorCode);
   if (!LDrawIni)
      Exit("Could not determine the LDrawDir.");


   int LDrawIniErrorCode;

   LDrawIni = LDrawIniGet(NULL, NULL, &LDrawIniErrorCode);
   if (!LDrawIni)
         char OldL3LabLDrawDir[L3_MAX_PATH];

         /* LDrawDir not set, see if L3Lab has a saved setting */
         strcpy(OldL3LabLDrawDir, GetProfileString("General settings", "LDrawDir", ""));
         if (OldL3LabLDrawDir[0])
            LDrawIni = LDrawIniGet(OldL3LabLDrawDir, "L3Lab old setting", &LDrawIniErrorCode);
   if (!LDrawIni)
      AfxMessageBox("You must specify the LDraw directory.",
   else if (!L3IsDir(LDrawIni->LDrawDir))
      char Str[1000];

      /* LDrawDir is not a valid directory */
      sprintf(Str, "LDrawDir '%s' is not a valid directory", LDrawIni->LDrawDir);

   i = LDrawIniComputeRealDirs(LDrawIni, 1, 1, NULL);
   if (!i)
      Exit("Failed to compute search dirs.");

FILE *OpenDatFile(char *DatName, int SearchForModel, int *Flags)
   FILE          *fp;
   register int   i;

   if (SearchForModel)
      /* Try current directory first. Note that DatName may be a full path. */
      if (Flags)
         *Flags = LDSDF_MODELDIR;
      fp = OpenDatFile2(NULL, DatName, SearchForModel);
      if (fp)
         return fp;
   for (i = 0; i < LDrawIni->nSearchDirs; i++)
      if (Flags)
         *Flags = LDrawIni->SearchDirs[i].Flags;
         if (SearchForModel)
            *Flags |= LDSDF_MODELDIR;
      fp = OpenDatFile2(LDrawIni->SearchDirs[i].Dir, DatName, SearchForModel);
      if (fp)
         return fp;
   return NULL;



Access the LDrawIni Subversion Repository

Please enjoy and let me know what you think.


Current uses

The following programs are known to use the LDrawIni library:

LDView logo    LDView by Travis Cobbs. Real-time 3D OpenGL viewer.

L3P logo    L3P by Lars C. Hassing. LDraw to POV-Ray converter.

L3Lab logo    L3Lab by Lars C. Hassing. Viewer/examiner.


SourceForge.net Logo

Last updated February 28, 2018